@anuma/sdk 10.5.1 → 10.5.3

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.
@@ -4879,6 +4879,63 @@ async function chunkRowSource(ctx, filter) {
4879
4879
  return fullScanChunkRowSource(ctx, filter);
4880
4880
  }
4881
4881
  }
4882
+ async function readChunkVectorRow(ctx, row, onUnreadable) {
4883
+ const version = Number(row.updated_at) || 0;
4884
+ const chunks3 = await readRawJsonField(row, "chunks", ctx.walletAddress);
4885
+ if (chunks3 && chunks3.length > 0) {
4886
+ return {
4887
+ entry: {
4888
+ version,
4889
+ chunks: chunks3.map((chunk) => decodeChunkVector(chunk.vector, onUnreadable))
4890
+ },
4891
+ chunks: chunks3
4892
+ };
4893
+ }
4894
+ const messageVector = await readRawJsonField(row, "vector", ctx.walletAddress);
4895
+ if (!messageVector || messageVector.length === 0) return null;
4896
+ return { entry: { version, chunks: [], fallback: Float32Array.from(messageVector) }, chunks: [] };
4897
+ }
4898
+ async function warmChunkVectorCacheOp(ctx, options) {
4899
+ const { chunkCache, embeddingModel, limit, signal } = options;
4900
+ const source = await chunkRowSource(ctx, {});
4901
+ const yieldIfDue = createTimeSliceYielder(CHUNK_SCAN_YIELD_BUDGET_MS);
4902
+ let keys = source.keys.filter(
4903
+ (key3) => !embeddingModel || key3.embeddingModel === null || key3.embeddingModel === embeddingModel
4904
+ );
4905
+ if (limit !== void 0 && keys.length > limit) {
4906
+ keys = keys.sort((a, b) => b.version - a.version).slice(0, limit);
4907
+ }
4908
+ const missIds = [];
4909
+ for (const key3 of keys) {
4910
+ await yieldIfDue();
4911
+ if (chunkCache.get(key3.id)?.version !== key3.version) missIds.push(key3.id);
4912
+ }
4913
+ let warmed = 0;
4914
+ let unreadableVectors = 0;
4915
+ for await (const row of loadVectorRowsInBatches(source, missIds)) {
4916
+ await yieldIfDue();
4917
+ const read = await readChunkVectorRow(ctx, row, () => {
4918
+ unreadableVectors++;
4919
+ });
4920
+ if (signal?.aborted) break;
4921
+ if (!read) continue;
4922
+ chunkCache.set(row.id, read.entry);
4923
+ warmed++;
4924
+ }
4925
+ warnUnreadableChunkVectors("warmChunkVectorCacheOp", unreadableVectors);
4926
+ return warmed;
4927
+ }
4928
+ async function* loadVectorRowsInBatches(source, ids) {
4929
+ for (let offset = 0; offset < ids.length; offset += CHUNK_VECTOR_BATCH_SIZE) {
4930
+ yield* await source.loadVectorRows(ids.slice(offset, offset + CHUNK_VECTOR_BATCH_SIZE));
4931
+ }
4932
+ }
4933
+ function warnUnreadableChunkVectors(operation, count2) {
4934
+ if (count2 === 0) return;
4935
+ getLogger().warn(
4936
+ `${operation}: could not read ${count2} chunk vectors and left them out of ranking \u2014 the stored value is corrupt, so those chunks stay unsearchable until the message is re-embedded via chunkAndEmbedAllMessages`
4937
+ );
4938
+ }
4882
4939
  async function searchChunksOp(ctx, queryVector, options) {
4883
4940
  const {
4884
4941
  limit = 10,
@@ -4947,45 +5004,39 @@ async function searchChunksOp(ctx, queryVector, options) {
4947
5004
  for (const row of rows) {
4948
5005
  await yieldIfDue();
4949
5006
  const id2 = row.id;
4950
- const version = Number(row.updated_at) || 0;
4951
5007
  const order = orderById.get(id2) ?? Number.MAX_SAFE_INTEGER;
4952
- const chunks3 = await readRawJsonField(row, "chunks", ctx.walletAddress);
4953
- if (chunks3 && chunks3.length > 0) {
4954
- const vectors = chunks3.map(
4955
- (chunk) => decodeChunkVector(chunk.vector, () => {
4956
- unreadableVectors++;
4957
- })
4958
- );
4959
- chunkCache?.set(id2, { version, chunks: vectors });
4960
- for (let ci = 0; ci < chunks3.length; ci++) {
4961
- const vec = vectors[ci];
4962
- if (vec.length === 0) continue;
4963
- const similarity = cosineSimilarity(queryVector, vec);
4964
- if (similarity >= minSimilarity) {
4965
- candidates.push({
4966
- id: id2,
4967
- version,
4968
- order,
4969
- similarity,
4970
- chunkTextSource: { kind: "chunk", chunk: chunks3[ci], siblings: chunks3 }
4971
- });
4972
- }
5008
+ const read = await readChunkVectorRow(ctx, row, () => {
5009
+ unreadableVectors++;
5010
+ });
5011
+ if (!read) continue;
5012
+ const { entry, chunks: chunks3 } = read;
5013
+ const { version } = entry;
5014
+ chunkCache?.set(id2, entry);
5015
+ if (entry.fallback) {
5016
+ const similarity = cosineSimilarity(queryVector, entry.fallback);
5017
+ if (similarity >= minSimilarity) {
5018
+ candidates.push({
5019
+ id: id2,
5020
+ version,
5021
+ order,
5022
+ similarity,
5023
+ chunkTextSource: { kind: "message" }
5024
+ });
4973
5025
  }
4974
- } else {
4975
- const messageVector = await readRawJsonField(row, "vector", ctx.walletAddress);
4976
- if (messageVector && messageVector.length > 0) {
4977
- const fallback = Float32Array.from(messageVector);
4978
- chunkCache?.set(id2, { version, chunks: [], fallback });
4979
- const similarity = cosineSimilarity(queryVector, fallback);
4980
- if (similarity >= minSimilarity) {
4981
- candidates.push({
4982
- id: id2,
4983
- version,
4984
- order,
4985
- similarity,
4986
- chunkTextSource: { kind: "message" }
4987
- });
4988
- }
5026
+ continue;
5027
+ }
5028
+ for (let ci = 0; ci < chunks3.length; ci++) {
5029
+ const vec = entry.chunks[ci];
5030
+ if (vec.length === 0) continue;
5031
+ const similarity = cosineSimilarity(queryVector, vec);
5032
+ if (similarity >= minSimilarity) {
5033
+ candidates.push({
5034
+ id: id2,
5035
+ version,
5036
+ order,
5037
+ similarity,
5038
+ chunkTextSource: { kind: "chunk", chunk: chunks3[ci], siblings: chunks3 }
5039
+ });
4989
5040
  }
4990
5041
  }
4991
5042
  }
@@ -4996,11 +5047,7 @@ async function searchChunksOp(ctx, queryVector, options) {
4996
5047
  `searchChunksOp: skipped ${staleSkipped} messages whose embedding model differs from the current model (${embeddingModel}) \u2014 re-embed via chunkAndEmbedAllMessages`
4997
5048
  );
4998
5049
  }
4999
- if (unreadableVectors > 0) {
5000
- getLogger().warn(
5001
- `searchChunksOp: could not read ${unreadableVectors} chunk vectors and left them out of ranking \u2014 the stored value is corrupt, so those chunks stay unsearchable until the message is re-embedded via chunkAndEmbedAllMessages`
5002
- );
5003
- }
5050
+ warnUnreadableChunkVectors("searchChunksOp", unreadableVectors);
5004
5051
  const topK = candidates.sort((a, b) => b.similarity - a.similarity || a.order - b.order).slice(0, limit);
5005
5052
  const topIds = Array.from(new Set(topK.map((c) => c.id)));
5006
5053
  const fullRows = await source.loadFullRows(topIds);
@@ -21405,12 +21452,16 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
21405
21452
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
21406
21453
  const uncachedTexts = [];
21407
21454
  const uncachedIndices = [];
21455
+ const resolvedVectors = /* @__PURE__ */ new Map();
21408
21456
  let staleReembedCount = 0;
21409
21457
  for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
21410
21458
  const content = memories[i].content;
21411
21459
  const memoryId = memories[i].uniqueId;
21412
21460
  const cached = cachedRowVector(cache, memoryId, memories[i].updatedAt, content);
21413
- if (cached && cached.length === queryEmbedding.length) continue;
21461
+ if (cached && cached.length === queryEmbedding.length) {
21462
+ resolvedVectors.set(memoryId, cached);
21463
+ continue;
21464
+ }
21414
21465
  if (cached) cache.delete(memoryId);
21415
21466
  const storedModel = memories[i].embeddingModel;
21416
21467
  const modelCompatible = (storedModel ?? currentModel) === currentModel;
@@ -21418,13 +21469,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
21418
21469
  try {
21419
21470
  const parsed = JSON.parse(memories[i].embedding);
21420
21471
  if (Array.isArray(parsed) && parsed.length === queryEmbedding.length) {
21421
- cacheRowVector(
21422
- cache,
21423
- memoryId,
21424
- Float32Array.from(parsed),
21425
- memories[i].updatedAt,
21426
- content
21427
- );
21472
+ const vector2 = Float32Array.from(parsed);
21473
+ resolvedVectors.set(memoryId, vector2);
21474
+ cacheRowVector(cache, memoryId, vector2, memories[i].updatedAt, content);
21428
21475
  continue;
21429
21476
  }
21430
21477
  } catch {
@@ -21457,20 +21504,17 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
21457
21504
  }
21458
21505
  if (newEmbeddings) {
21459
21506
  for (let j = 0; j < uncachedTexts.length; j++) {
21460
- cacheRowVector(
21461
- cache,
21462
- memories[uncachedIndices[j]].uniqueId,
21463
- Float32Array.from(newEmbeddings[j]),
21464
- memories[uncachedIndices[j]].updatedAt,
21465
- memories[uncachedIndices[j]].content
21466
- );
21507
+ const memory = memories[uncachedIndices[j]];
21508
+ const vector2 = Float32Array.from(newEmbeddings[j]);
21509
+ resolvedVectors.set(memory.uniqueId, vector2);
21510
+ cacheRowVector(cache, memory.uniqueId, vector2, memory.updatedAt, memory.content);
21467
21511
  }
21468
21512
  }
21469
21513
  }
21470
21514
  embeddedItems = memories.map((m) => ({
21471
21515
  id: m.uniqueId,
21472
21516
  content: m.content,
21473
- embedding: cache.get(m.uniqueId) ?? [],
21517
+ embedding: resolvedVectors.get(m.uniqueId) ?? [],
21474
21518
  createdAt: m.createdAt,
21475
21519
  updatedAt: m.updatedAt,
21476
21520
  proofCount: m.proofCount,
@@ -29910,6 +29954,9 @@ var WatermelonChatStorageAdapter = class {
29910
29954
  searchChunks(queryVector, options) {
29911
29955
  return searchChunksOp(this.ctx, queryVector, options);
29912
29956
  }
29957
+ warmChunkCache(options) {
29958
+ return warmChunkVectorCacheOp(this.ctx, options);
29959
+ }
29913
29960
  getSummary(conversationId) {
29914
29961
  return getConversationSummaryOp(
29915
29962
  createSummaryContext(this.ctx.database, this.ctx),
@@ -4436,6 +4436,13 @@ interface ChatBackend extends ChatStorageAdapter {
4436
4436
  uniqueId: string;
4437
4437
  }): Promise<StoredMessage>;
4438
4438
  searchChunks(queryVector: number[], options?: ChatChunkSearchOptions): Promise<ChunkSearchResult[]>;
4439
+ /** Fills a chunk vector cache ahead of the first search, for backends that score on the device. */
4440
+ warmChunkCache?(options: {
4441
+ chunkCache: ChunkVectorCache;
4442
+ embeddingModel?: string;
4443
+ limit?: number;
4444
+ signal?: AbortSignal;
4445
+ }): Promise<number>;
4439
4446
  getSummary(conversationId: string): Promise<StoredConversationSummary | null>;
4440
4447
  upsertSummary(conversationId: string, summary: string, summarizedUpTo: string, tokenCount: number): Promise<StoredConversationSummary>;
4441
4448
  deleteSummary(conversationId: string): Promise<void>;
@@ -4436,6 +4436,13 @@ interface ChatBackend extends ChatStorageAdapter {
4436
4436
  uniqueId: string;
4437
4437
  }): Promise<StoredMessage>;
4438
4438
  searchChunks(queryVector: number[], options?: ChatChunkSearchOptions): Promise<ChunkSearchResult[]>;
4439
+ /** Fills a chunk vector cache ahead of the first search, for backends that score on the device. */
4440
+ warmChunkCache?(options: {
4441
+ chunkCache: ChunkVectorCache;
4442
+ embeddingModel?: string;
4443
+ limit?: number;
4444
+ signal?: AbortSignal;
4445
+ }): Promise<number>;
4439
4446
  getSummary(conversationId: string): Promise<StoredConversationSummary | null>;
4440
4447
  upsertSummary(conversationId: string, summary: string, summarizedUpTo: string, tokenCount: number): Promise<StoredConversationSummary>;
4441
4448
  deleteSummary(conversationId: string): Promise<void>;
@@ -3234,6 +3234,63 @@ async function chunkRowSource(ctx, filter) {
3234
3234
  return fullScanChunkRowSource(ctx, filter);
3235
3235
  }
3236
3236
  }
3237
+ async function readChunkVectorRow(ctx, row, onUnreadable) {
3238
+ const version = Number(row.updated_at) || 0;
3239
+ const chunks3 = await readRawJsonField(row, "chunks", ctx.walletAddress);
3240
+ if (chunks3 && chunks3.length > 0) {
3241
+ return {
3242
+ entry: {
3243
+ version,
3244
+ chunks: chunks3.map((chunk) => decodeChunkVector(chunk.vector, onUnreadable))
3245
+ },
3246
+ chunks: chunks3
3247
+ };
3248
+ }
3249
+ const messageVector = await readRawJsonField(row, "vector", ctx.walletAddress);
3250
+ if (!messageVector || messageVector.length === 0) return null;
3251
+ return { entry: { version, chunks: [], fallback: Float32Array.from(messageVector) }, chunks: [] };
3252
+ }
3253
+ async function warmChunkVectorCacheOp(ctx, options) {
3254
+ const { chunkCache, embeddingModel, limit, signal } = options;
3255
+ const source = await chunkRowSource(ctx, {});
3256
+ const yieldIfDue = createTimeSliceYielder(CHUNK_SCAN_YIELD_BUDGET_MS);
3257
+ let keys = source.keys.filter(
3258
+ (key3) => !embeddingModel || key3.embeddingModel === null || key3.embeddingModel === embeddingModel
3259
+ );
3260
+ if (limit !== void 0 && keys.length > limit) {
3261
+ keys = keys.sort((a, b) => b.version - a.version).slice(0, limit);
3262
+ }
3263
+ const missIds = [];
3264
+ for (const key3 of keys) {
3265
+ await yieldIfDue();
3266
+ if (chunkCache.get(key3.id)?.version !== key3.version) missIds.push(key3.id);
3267
+ }
3268
+ let warmed = 0;
3269
+ let unreadableVectors = 0;
3270
+ for await (const row of loadVectorRowsInBatches(source, missIds)) {
3271
+ await yieldIfDue();
3272
+ const read = await readChunkVectorRow(ctx, row, () => {
3273
+ unreadableVectors++;
3274
+ });
3275
+ if (signal?.aborted) break;
3276
+ if (!read) continue;
3277
+ chunkCache.set(row.id, read.entry);
3278
+ warmed++;
3279
+ }
3280
+ warnUnreadableChunkVectors("warmChunkVectorCacheOp", unreadableVectors);
3281
+ return warmed;
3282
+ }
3283
+ async function* loadVectorRowsInBatches(source, ids) {
3284
+ for (let offset = 0; offset < ids.length; offset += CHUNK_VECTOR_BATCH_SIZE) {
3285
+ yield* await source.loadVectorRows(ids.slice(offset, offset + CHUNK_VECTOR_BATCH_SIZE));
3286
+ }
3287
+ }
3288
+ function warnUnreadableChunkVectors(operation, count2) {
3289
+ if (count2 === 0) return;
3290
+ getLogger().warn(
3291
+ `${operation}: could not read ${count2} chunk vectors and left them out of ranking \u2014 the stored value is corrupt, so those chunks stay unsearchable until the message is re-embedded via chunkAndEmbedAllMessages`
3292
+ );
3293
+ }
3237
3294
  async function searchChunksOp(ctx, queryVector, options) {
3238
3295
  const {
3239
3296
  limit = 10,
@@ -3302,45 +3359,39 @@ async function searchChunksOp(ctx, queryVector, options) {
3302
3359
  for (const row of rows) {
3303
3360
  await yieldIfDue();
3304
3361
  const id2 = row.id;
3305
- const version = Number(row.updated_at) || 0;
3306
3362
  const order = orderById.get(id2) ?? Number.MAX_SAFE_INTEGER;
3307
- const chunks3 = await readRawJsonField(row, "chunks", ctx.walletAddress);
3308
- if (chunks3 && chunks3.length > 0) {
3309
- const vectors = chunks3.map(
3310
- (chunk) => decodeChunkVector(chunk.vector, () => {
3311
- unreadableVectors++;
3312
- })
3313
- );
3314
- chunkCache?.set(id2, { version, chunks: vectors });
3315
- for (let ci = 0; ci < chunks3.length; ci++) {
3316
- const vec = vectors[ci];
3317
- if (vec.length === 0) continue;
3318
- const similarity = cosineSimilarity(queryVector, vec);
3319
- if (similarity >= minSimilarity) {
3320
- candidates.push({
3321
- id: id2,
3322
- version,
3323
- order,
3324
- similarity,
3325
- chunkTextSource: { kind: "chunk", chunk: chunks3[ci], siblings: chunks3 }
3326
- });
3327
- }
3363
+ const read = await readChunkVectorRow(ctx, row, () => {
3364
+ unreadableVectors++;
3365
+ });
3366
+ if (!read) continue;
3367
+ const { entry, chunks: chunks3 } = read;
3368
+ const { version } = entry;
3369
+ chunkCache?.set(id2, entry);
3370
+ if (entry.fallback) {
3371
+ const similarity = cosineSimilarity(queryVector, entry.fallback);
3372
+ if (similarity >= minSimilarity) {
3373
+ candidates.push({
3374
+ id: id2,
3375
+ version,
3376
+ order,
3377
+ similarity,
3378
+ chunkTextSource: { kind: "message" }
3379
+ });
3328
3380
  }
3329
- } else {
3330
- const messageVector = await readRawJsonField(row, "vector", ctx.walletAddress);
3331
- if (messageVector && messageVector.length > 0) {
3332
- const fallback = Float32Array.from(messageVector);
3333
- chunkCache?.set(id2, { version, chunks: [], fallback });
3334
- const similarity = cosineSimilarity(queryVector, fallback);
3335
- if (similarity >= minSimilarity) {
3336
- candidates.push({
3337
- id: id2,
3338
- version,
3339
- order,
3340
- similarity,
3341
- chunkTextSource: { kind: "message" }
3342
- });
3343
- }
3381
+ continue;
3382
+ }
3383
+ for (let ci = 0; ci < chunks3.length; ci++) {
3384
+ const vec = entry.chunks[ci];
3385
+ if (vec.length === 0) continue;
3386
+ const similarity = cosineSimilarity(queryVector, vec);
3387
+ if (similarity >= minSimilarity) {
3388
+ candidates.push({
3389
+ id: id2,
3390
+ version,
3391
+ order,
3392
+ similarity,
3393
+ chunkTextSource: { kind: "chunk", chunk: chunks3[ci], siblings: chunks3 }
3394
+ });
3344
3395
  }
3345
3396
  }
3346
3397
  }
@@ -3351,11 +3402,7 @@ async function searchChunksOp(ctx, queryVector, options) {
3351
3402
  `searchChunksOp: skipped ${staleSkipped} messages whose embedding model differs from the current model (${embeddingModel}) \u2014 re-embed via chunkAndEmbedAllMessages`
3352
3403
  );
3353
3404
  }
3354
- if (unreadableVectors > 0) {
3355
- getLogger().warn(
3356
- `searchChunksOp: could not read ${unreadableVectors} chunk vectors and left them out of ranking \u2014 the stored value is corrupt, so those chunks stay unsearchable until the message is re-embedded via chunkAndEmbedAllMessages`
3357
- );
3358
- }
3405
+ warnUnreadableChunkVectors("searchChunksOp", unreadableVectors);
3359
3406
  const topK = candidates.sort((a, b) => b.similarity - a.similarity || a.order - b.order).slice(0, limit);
3360
3407
  const topIds = Array.from(new Set(topK.map((c) => c.id)));
3361
3408
  const fullRows = await source.loadFullRows(topIds);
@@ -19712,12 +19759,16 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
19712
19759
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
19713
19760
  const uncachedTexts = [];
19714
19761
  const uncachedIndices = [];
19762
+ const resolvedVectors = /* @__PURE__ */ new Map();
19715
19763
  let staleReembedCount = 0;
19716
19764
  for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
19717
19765
  const content = memories[i].content;
19718
19766
  const memoryId = memories[i].uniqueId;
19719
19767
  const cached = cachedRowVector(cache, memoryId, memories[i].updatedAt, content);
19720
- if (cached && cached.length === queryEmbedding.length) continue;
19768
+ if (cached && cached.length === queryEmbedding.length) {
19769
+ resolvedVectors.set(memoryId, cached);
19770
+ continue;
19771
+ }
19721
19772
  if (cached) cache.delete(memoryId);
19722
19773
  const storedModel = memories[i].embeddingModel;
19723
19774
  const modelCompatible = (storedModel ?? currentModel) === currentModel;
@@ -19725,13 +19776,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
19725
19776
  try {
19726
19777
  const parsed = JSON.parse(memories[i].embedding);
19727
19778
  if (Array.isArray(parsed) && parsed.length === queryEmbedding.length) {
19728
- cacheRowVector(
19729
- cache,
19730
- memoryId,
19731
- Float32Array.from(parsed),
19732
- memories[i].updatedAt,
19733
- content
19734
- );
19779
+ const vector2 = Float32Array.from(parsed);
19780
+ resolvedVectors.set(memoryId, vector2);
19781
+ cacheRowVector(cache, memoryId, vector2, memories[i].updatedAt, content);
19735
19782
  continue;
19736
19783
  }
19737
19784
  } catch {
@@ -19764,20 +19811,17 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
19764
19811
  }
19765
19812
  if (newEmbeddings) {
19766
19813
  for (let j = 0; j < uncachedTexts.length; j++) {
19767
- cacheRowVector(
19768
- cache,
19769
- memories[uncachedIndices[j]].uniqueId,
19770
- Float32Array.from(newEmbeddings[j]),
19771
- memories[uncachedIndices[j]].updatedAt,
19772
- memories[uncachedIndices[j]].content
19773
- );
19814
+ const memory = memories[uncachedIndices[j]];
19815
+ const vector2 = Float32Array.from(newEmbeddings[j]);
19816
+ resolvedVectors.set(memory.uniqueId, vector2);
19817
+ cacheRowVector(cache, memory.uniqueId, vector2, memory.updatedAt, memory.content);
19774
19818
  }
19775
19819
  }
19776
19820
  }
19777
19821
  embeddedItems = memories.map((m) => ({
19778
19822
  id: m.uniqueId,
19779
19823
  content: m.content,
19780
- embedding: cache.get(m.uniqueId) ?? [],
19824
+ embedding: resolvedVectors.get(m.uniqueId) ?? [],
19781
19825
  createdAt: m.createdAt,
19782
19826
  updatedAt: m.updatedAt,
19783
19827
  proofCount: m.proofCount,
@@ -28181,6 +28225,9 @@ var WatermelonChatStorageAdapter = class {
28181
28225
  searchChunks(queryVector, options) {
28182
28226
  return searchChunksOp(this.ctx, queryVector, options);
28183
28227
  }
28228
+ warmChunkCache(options) {
28229
+ return warmChunkVectorCacheOp(this.ctx, options);
28230
+ }
28184
28231
  getSummary(conversationId) {
28185
28232
  return getConversationSummaryOp(
28186
28233
  createSummaryContext(this.ctx.database, this.ctx),