@equationalapplications/core-llm-wiki 7.8.0 → 7.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/{chunk-M76CF2Q6.mjs → chunk-7FRLQ7ZO.mjs} +83 -129
- package/dist/chunk-7FRLQ7ZO.mjs.map +1 -0
- package/dist/index.d.mts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +305 -130
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +227 -6
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-CWZaXKLj.d.mts → testing-Bf6etdUy.d.mts} +156 -26
- package/dist/{testing-CWZaXKLj.d.ts → testing-Bf6etdUy.d.ts} +156 -26
- package/dist/testing.d.mts +1 -2
- package/dist/testing.d.ts +1 -2
- package/dist/testing.js +83 -131
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-M76CF2Q6.mjs.map +0 -1
package/dist/testing.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var coreOkf = require('@equationalapplications/core-okf');
|
|
4
|
-
var MiniSearch = require('minisearch');
|
|
5
|
-
|
|
6
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
-
|
|
8
|
-
var MiniSearch__default = /*#__PURE__*/_interopDefault(MiniSearch);
|
|
9
4
|
|
|
10
5
|
// src/db/sqliteCodes.ts
|
|
11
6
|
var SQLITE_RESULT_CODE_NAMES = {
|
|
@@ -3183,7 +3178,7 @@ async function gateCandidates(deps, ctx, candidates, cfg) {
|
|
|
3183
3178
|
}
|
|
3184
3179
|
}
|
|
3185
3180
|
if (!ranked) {
|
|
3186
|
-
ranked = deps.searchService.searchKeyword(`${c.fact.title} ${c.fact.body}`, [entityId], cfg.k + nonLive.size).filter((h) => !nonLive.has(h.id)).slice(0, cfg.k).map((h) => ({ id: h.id, score: null }));
|
|
3181
|
+
ranked = (await deps.searchService.searchKeyword(`${c.fact.title} ${c.fact.body}`, [entityId], cfg.k + nonLive.size)).filter((h) => !nonLive.has(h.id)).slice(0, cfg.k).map((h) => ({ id: h.id, score: null }));
|
|
3187
3182
|
}
|
|
3188
3183
|
const facts = ranked.length > 0 ? await deps.entryRepo.findByIds(ranked.map((r) => r.id), [entityId]) : [];
|
|
3189
3184
|
const byId = new Map(facts.map((f) => [f.id, f]));
|
|
@@ -4634,7 +4629,7 @@ var MaintenanceService = class {
|
|
|
4634
4629
|
if (!query) return [];
|
|
4635
4630
|
const cached = cache?.get(query);
|
|
4636
4631
|
if (cached) return cached;
|
|
4637
|
-
const hits = this.searchService.searchKeyword(
|
|
4632
|
+
const hits = await this.searchService.searchKeyword(
|
|
4638
4633
|
query,
|
|
4639
4634
|
[entityId],
|
|
4640
4635
|
cap * HEAL_ANCHOR_SEARCH_OVERFETCH
|
|
@@ -4897,7 +4892,7 @@ var RetrievalService = class {
|
|
|
4897
4892
|
let miniSearchScores;
|
|
4898
4893
|
if (effectivePreFilterLimit !== void 0) {
|
|
4899
4894
|
populateCache = false;
|
|
4900
|
-
const preResults = this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, Number.MAX_SAFE_INTEGER).filter((r) => !excludedIds.has(r.id));
|
|
4895
|
+
const preResults = (await this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, Number.MAX_SAFE_INTEGER)).filter((r) => !excludedIds.has(r.id));
|
|
4901
4896
|
if (preResults.length === 0) {
|
|
4902
4897
|
candidateRows = null;
|
|
4903
4898
|
} else {
|
|
@@ -4924,7 +4919,7 @@ var RetrievalService = class {
|
|
|
4924
4919
|
candidateRows = this._withoutIds(await this.entryRepo.findWithEmbeddingsByEntityIds(scoredEntityIds), excludedIds);
|
|
4925
4920
|
}
|
|
4926
4921
|
if (weight !== void 0 && weight < 1) {
|
|
4927
|
-
miniSearchScores = this.searchService.
|
|
4922
|
+
miniSearchScores = await this.searchService.getKeywordScores(trimmedQuery, scoredEntityIds);
|
|
4928
4923
|
}
|
|
4929
4924
|
}
|
|
4930
4925
|
if (candidateRows === null) {
|
|
@@ -5167,7 +5162,7 @@ var RetrievalService = class {
|
|
|
5167
5162
|
const hasActiveFloorsKeywordFallback = sanitizedTierFloors !== void 0 && Object.values(sanitizedTierFloors).some((f) => f > 0);
|
|
5168
5163
|
const keywordOversampledLimit = hasActiveFloorsKeywordFallback ? Number.MAX_SAFE_INTEGER : padLimit(Math.max(maxResults * 2, maxResults + 50));
|
|
5169
5164
|
const preFilteredIds = effectivePreFilterLimit !== void 0 ? new Set(candidateRows.map((r) => r.id)) : void 0;
|
|
5170
|
-
const keywordResults = this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, keywordOversampledLimit);
|
|
5165
|
+
const keywordResults = await this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, keywordOversampledLimit);
|
|
5171
5166
|
const topResults = preFilteredIds === void 0 ? keywordResults : keywordResults.filter((r) => preFilteredIds.has(r.id));
|
|
5172
5167
|
const topResultIds = new Set(topResults.map((r) => r.id));
|
|
5173
5168
|
const candidateMap = new Map(candidateRows.filter((r) => topResultIds.has(r.id)).map((row) => [row.id, row]));
|
|
@@ -5270,7 +5265,7 @@ var RetrievalService = class {
|
|
|
5270
5265
|
if (!usedEmbed && scoredEntityIds.length > 0) {
|
|
5271
5266
|
const hasActiveFloors = sanitizedTierFloors !== void 0 && Object.values(sanitizedTierFloors).some((f) => f > 0);
|
|
5272
5267
|
const fallbackOversampledLimit = hasActiveFloors ? Number.MAX_SAFE_INTEGER : padLimit(Math.max(maxResults * 2, maxResults + 50));
|
|
5273
|
-
const results = this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, fallbackOversampledLimit).filter((r) => !excludedIds.has(r.id));
|
|
5268
|
+
const results = (await this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, fallbackOversampledLimit)).filter((r) => !excludedIds.has(r.id));
|
|
5274
5269
|
const candidates = results.map((r) => ({
|
|
5275
5270
|
id: r.id,
|
|
5276
5271
|
entity_id: r.entity_id,
|
|
@@ -5407,10 +5402,29 @@ var RetrievalService = class {
|
|
|
5407
5402
|
return scored;
|
|
5408
5403
|
}
|
|
5409
5404
|
};
|
|
5405
|
+
|
|
5406
|
+
// src/utils/indexDoc.ts
|
|
5407
|
+
function toIndexDoc(row) {
|
|
5408
|
+
return {
|
|
5409
|
+
id: row.id,
|
|
5410
|
+
entity_id: row.entity_id,
|
|
5411
|
+
title: row.title,
|
|
5412
|
+
body: row.body,
|
|
5413
|
+
tags: (() => {
|
|
5414
|
+
try {
|
|
5415
|
+
const parsed = JSON.parse(row.tags);
|
|
5416
|
+
return Array.isArray(parsed) ? parsed.join(" ") : row.tags;
|
|
5417
|
+
} catch {
|
|
5418
|
+
return row.tags;
|
|
5419
|
+
}
|
|
5420
|
+
})()
|
|
5421
|
+
};
|
|
5422
|
+
}
|
|
5423
|
+
|
|
5424
|
+
// src/services/SearchService.ts
|
|
5410
5425
|
var _SearchService = class _SearchService {
|
|
5411
|
-
constructor(entryRepo) {
|
|
5426
|
+
constructor(entryRepo, indexStrategy) {
|
|
5412
5427
|
this.entryRepo = entryRepo;
|
|
5413
|
-
this.miniSearchEntryIdsByEntity = /* @__PURE__ */ new Map();
|
|
5414
5428
|
this.vectorCache = /* @__PURE__ */ new Map();
|
|
5415
5429
|
/**
|
|
5416
5430
|
* Serializes rebuilds. `rebuildIndex` awaits a repository read between
|
|
@@ -5436,35 +5450,13 @@ var _SearchService = class _SearchService {
|
|
|
5436
5450
|
* its flag must outlive the turn (#233 review).
|
|
5437
5451
|
*/
|
|
5438
5452
|
this.staleEpochs = /* @__PURE__ */ new Map();
|
|
5439
|
-
this.
|
|
5440
|
-
}
|
|
5441
|
-
/**
|
|
5442
|
-
* A fresh index with the production options. clearAll() swaps one in because
|
|
5443
|
-
* MiniSearch.removeAll() empties the index but leaves dirtCount (and its
|
|
5444
|
-
* vacuum bookkeeping) at its old value, which would trip syncEntries'
|
|
5445
|
-
* conditional vacuum early after a clear.
|
|
5446
|
-
*/
|
|
5447
|
-
createMiniSearch() {
|
|
5448
|
-
return new MiniSearch__default.default({
|
|
5449
|
-
fields: ["title", "body", "tags"],
|
|
5450
|
-
storeFields: ["entity_id"],
|
|
5451
|
-
// Vacuuming is driven explicitly at the end of each serialized rebuild
|
|
5452
|
-
// (see sync). Auto-vacuum fires on its own schedule, asynchronously with
|
|
5453
|
-
// respect to the caller, and traversing the tree mid-rebuild is what
|
|
5454
|
-
// threw the uncaught TypeError in MiniSearch.performVacuuming (#64).
|
|
5455
|
-
autoVacuum: false,
|
|
5456
|
-
searchOptions: {
|
|
5457
|
-
boost: { title: 2 },
|
|
5458
|
-
fuzzy: 0.2,
|
|
5459
|
-
prefix: true
|
|
5460
|
-
}
|
|
5461
|
-
});
|
|
5453
|
+
this.indexStrategy = indexStrategy;
|
|
5462
5454
|
}
|
|
5463
5455
|
/**
|
|
5464
5456
|
* Rebuilds the search index and clears the vector cache for a given entity.
|
|
5465
5457
|
* A direct replacement for manually syncing state after a DB transaction.
|
|
5466
5458
|
*
|
|
5467
|
-
* Rebuilds are serialized per instance and never reject: the
|
|
5459
|
+
* Rebuilds are serialized per instance and never reject: the keyword index
|
|
5468
5460
|
* is a rebuildable cache over SQLite, so degraded keyword search is the
|
|
5469
5461
|
* correct failure mode and killing the host process is not.
|
|
5470
5462
|
*/
|
|
@@ -5473,19 +5465,21 @@ var _SearchService = class _SearchService {
|
|
|
5473
5465
|
try {
|
|
5474
5466
|
try {
|
|
5475
5467
|
const epochsBefore = new Map(this.staleEpochs);
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
this.staleEntities.delete(entityId);
|
|
5480
|
-
}
|
|
5481
|
-
} else {
|
|
5468
|
+
if (entityId === void 0) {
|
|
5469
|
+
const rows = await this.entryRepo.findMiniSearchRows();
|
|
5470
|
+
await this.indexStrategy.replaceAll(rows.map(toIndexDoc));
|
|
5482
5471
|
for (const id of [...this.staleEntities]) {
|
|
5483
5472
|
if ((this.staleEpochs.get(id) ?? 0) === (epochsBefore.get(id) ?? 0)) {
|
|
5484
5473
|
this.staleEntities.delete(id);
|
|
5485
5474
|
}
|
|
5486
5475
|
}
|
|
5476
|
+
} else {
|
|
5477
|
+
await this.rebuildIndex(entityId);
|
|
5478
|
+
if ((this.staleEpochs.get(entityId) ?? 0) === (epochsBefore.get(entityId) ?? 0)) {
|
|
5479
|
+
this.staleEntities.delete(entityId);
|
|
5480
|
+
}
|
|
5487
5481
|
}
|
|
5488
|
-
await this.
|
|
5482
|
+
await this.indexStrategy.vacuum?.();
|
|
5489
5483
|
} finally {
|
|
5490
5484
|
this.evictCache(entityId);
|
|
5491
5485
|
}
|
|
@@ -5510,27 +5504,20 @@ var _SearchService = class _SearchService {
|
|
|
5510
5504
|
*/
|
|
5511
5505
|
async syncEntries(entityId, ids) {
|
|
5512
5506
|
const uniqueIds = [...new Set(ids)];
|
|
5513
|
-
|
|
5507
|
+
const indexed = this.indexStrategy.hasIndexedEntity?.(entityId);
|
|
5508
|
+
if (uniqueIds.length === 0 && !this.staleEntities.has(entityId) && indexed === true) {
|
|
5514
5509
|
return this.syncChain;
|
|
5515
5510
|
}
|
|
5516
5511
|
const work = this.syncChain.then(async () => {
|
|
5517
5512
|
try {
|
|
5518
5513
|
try {
|
|
5519
5514
|
const epochsBefore = new Map(this.staleEpochs);
|
|
5520
|
-
const needsRebuild = () => this.staleEntities.has(entityId) ||
|
|
5515
|
+
const needsRebuild = () => this.staleEntities.has(entityId) || this.indexStrategy.hasIndexedEntity?.(entityId) !== true;
|
|
5521
5516
|
if (!needsRebuild()) {
|
|
5522
5517
|
const rows = await this.entryRepo.findMiniSearchRowsByIds(entityId, uniqueIds);
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
if (tracked.delete(id) && this.miniSearch.has(id)) this.miniSearch.discard(id);
|
|
5527
|
-
}
|
|
5528
|
-
const documents = rows.map((row) => this.normalizeMiniSearchRow(row));
|
|
5529
|
-
if (documents.length > 0) this.miniSearch.addAll(documents);
|
|
5530
|
-
for (const document of documents) tracked.add(document.id);
|
|
5531
|
-
if (this.miniSearch.dirtCount > 0) {
|
|
5532
|
-
await this.miniSearch.vacuum();
|
|
5533
|
-
}
|
|
5518
|
+
if (!this.staleEntities.has(entityId)) {
|
|
5519
|
+
await this.indexStrategy.replace(entityId, uniqueIds, rows.map(toIndexDoc));
|
|
5520
|
+
await this.indexStrategy.vacuum?.();
|
|
5534
5521
|
return;
|
|
5535
5522
|
}
|
|
5536
5523
|
}
|
|
@@ -5538,7 +5525,7 @@ var _SearchService = class _SearchService {
|
|
|
5538
5525
|
if ((this.staleEpochs.get(entityId) ?? 0) === (epochsBefore.get(entityId) ?? 0)) {
|
|
5539
5526
|
this.staleEntities.delete(entityId);
|
|
5540
5527
|
}
|
|
5541
|
-
await this.
|
|
5528
|
+
await this.indexStrategy.vacuum?.();
|
|
5542
5529
|
} finally {
|
|
5543
5530
|
this.evictCache(entityId);
|
|
5544
5531
|
}
|
|
@@ -5558,6 +5545,16 @@ var _SearchService = class _SearchService {
|
|
|
5558
5545
|
this.staleEntities.add(entityId);
|
|
5559
5546
|
this.staleEpochs.set(entityId, (this.staleEpochs.get(entityId) ?? 0) + 1);
|
|
5560
5547
|
}
|
|
5548
|
+
/**
|
|
5549
|
+
* Runs syncEntries(id, []) for each entity marked stale when this is called,
|
|
5550
|
+
* so only those entities are rebuilt. Each rebuild still takes its own turn
|
|
5551
|
+
* on the sync chain, and like syncEntries this never rejects. With nothing
|
|
5552
|
+
* stale it resolves at once, without waiting on work already on the chain.
|
|
5553
|
+
*/
|
|
5554
|
+
async syncStale() {
|
|
5555
|
+
const ids = [...this.staleEntities];
|
|
5556
|
+
await Promise.all(ids.map((id) => this.syncEntries(id, [])));
|
|
5557
|
+
}
|
|
5561
5558
|
/**
|
|
5562
5559
|
* Clears the parsed vector cache. Useful for mid-loop flush guarantees
|
|
5563
5560
|
* or memory pressure evictions.
|
|
@@ -5572,39 +5569,28 @@ var _SearchService = class _SearchService {
|
|
|
5572
5569
|
/**
|
|
5573
5570
|
* Fully resets the search service.
|
|
5574
5571
|
*/
|
|
5575
|
-
clearAll() {
|
|
5572
|
+
async clearAll() {
|
|
5576
5573
|
this.vectorCache.clear();
|
|
5577
|
-
|
|
5578
|
-
this.miniSearchEntryIdsByEntity.clear();
|
|
5574
|
+
await this.indexStrategy.replaceAll([]);
|
|
5579
5575
|
this.staleEntities.clear();
|
|
5580
5576
|
this.staleEpochs.clear();
|
|
5581
5577
|
}
|
|
5582
5578
|
/**
|
|
5583
|
-
* Executes a keyword search against the active
|
|
5579
|
+
* Executes a keyword search against the active index strategy.
|
|
5584
5580
|
*/
|
|
5585
|
-
searchKeyword(query, entityIds, limit) {
|
|
5586
|
-
const
|
|
5587
|
-
const results = this.miniSearch.search(query, {
|
|
5588
|
-
filter: (r) => entityIdSet.has(r.entity_id),
|
|
5589
|
-
combineWith: "OR"
|
|
5590
|
-
});
|
|
5581
|
+
async searchKeyword(query, entityIds, limit) {
|
|
5582
|
+
const results = finiteResults(await this.indexStrategy.search(query, { entityIds, limit }));
|
|
5591
5583
|
return results.sort((a, b) => this._compareSearchResults(a, b)).slice(0, limit);
|
|
5592
5584
|
}
|
|
5593
5585
|
/**
|
|
5594
|
-
* Pre-fetches
|
|
5586
|
+
* Pre-fetches keyword scores for candidate hydration, used during hybrid weighting.
|
|
5595
5587
|
*/
|
|
5596
|
-
|
|
5597
|
-
const
|
|
5598
|
-
|
|
5599
|
-
filter: (r) => entityIdSet.has(r.entity_id),
|
|
5600
|
-
combineWith: "OR"
|
|
5601
|
-
}).sort((a, b) => this._compareSearchResults(a, b));
|
|
5602
|
-
if (preFilterLimit !== void 0) {
|
|
5603
|
-
results = results.slice(0, preFilterLimit);
|
|
5604
|
-
}
|
|
5588
|
+
async getKeywordScores(query, entityIds, preFilterLimit) {
|
|
5589
|
+
const opts = preFilterLimit !== void 0 ? { entityIds, limit: preFilterLimit, preFilterLimit } : { entityIds, limit: Number.MAX_SAFE_INTEGER };
|
|
5590
|
+
const results = finiteResults(await this.indexStrategy.search(query, opts));
|
|
5605
5591
|
if (results.length === 0) return /* @__PURE__ */ new Map();
|
|
5606
|
-
const
|
|
5607
|
-
return new Map(results.map((r) => [r.id, r.score /
|
|
5592
|
+
const maxScore = Math.max(1, results[0]?.score ?? 1);
|
|
5593
|
+
return new Map(results.map((r) => [r.id, r.score / maxScore]));
|
|
5608
5594
|
}
|
|
5609
5595
|
/**
|
|
5610
5596
|
* Score candidate rows using in-process JS cosine similarity.
|
|
@@ -5666,53 +5652,16 @@ var _SearchService = class _SearchService {
|
|
|
5666
5652
|
return scored.slice(0, limit);
|
|
5667
5653
|
}
|
|
5668
5654
|
// --- Internal Index Management ---
|
|
5655
|
+
/**
|
|
5656
|
+
* Rebuild a single entity's index from scratch. Reads every row for
|
|
5657
|
+
* `entityId` from the repository (already filtered by `deleted_at IS NULL`)
|
|
5658
|
+
* and hands the lot to `indexStrategy.replaceEntity`, which owns the
|
|
5659
|
+
* drop-then-add bookkeeping so callers don't need to know the strategy's
|
|
5660
|
+
* id-tracking shape.
|
|
5661
|
+
*/
|
|
5669
5662
|
async rebuildIndex(entityId) {
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
const previousIds = this.miniSearchEntryIdsByEntity.get(entityId);
|
|
5673
|
-
if (previousIds) {
|
|
5674
|
-
for (const id of previousIds) {
|
|
5675
|
-
this.miniSearch.discard(id);
|
|
5676
|
-
}
|
|
5677
|
-
}
|
|
5678
|
-
const documents2 = rows2.map((row) => this.normalizeMiniSearchRow(row));
|
|
5679
|
-
if (documents2.length > 0) {
|
|
5680
|
-
this.miniSearch.addAll(documents2);
|
|
5681
|
-
}
|
|
5682
|
-
this.miniSearchEntryIdsByEntity.set(
|
|
5683
|
-
entityId,
|
|
5684
|
-
new Set(documents2.map((document) => document.id))
|
|
5685
|
-
);
|
|
5686
|
-
return;
|
|
5687
|
-
}
|
|
5688
|
-
const rows = await this.entryRepo.findMiniSearchRows();
|
|
5689
|
-
this.miniSearch.removeAll();
|
|
5690
|
-
this.miniSearchEntryIdsByEntity.clear();
|
|
5691
|
-
const documents = rows.map((row) => this.normalizeMiniSearchRow(row));
|
|
5692
|
-
if (documents.length > 0) {
|
|
5693
|
-
this.miniSearch.addAll(documents);
|
|
5694
|
-
}
|
|
5695
|
-
for (const document of documents) {
|
|
5696
|
-
const ids = this.miniSearchEntryIdsByEntity.get(document.entity_id) ?? /* @__PURE__ */ new Set();
|
|
5697
|
-
ids.add(document.id);
|
|
5698
|
-
this.miniSearchEntryIdsByEntity.set(document.entity_id, ids);
|
|
5699
|
-
}
|
|
5700
|
-
}
|
|
5701
|
-
normalizeMiniSearchRow(row) {
|
|
5702
|
-
return {
|
|
5703
|
-
id: row.id,
|
|
5704
|
-
entity_id: row.entity_id,
|
|
5705
|
-
title: row.title,
|
|
5706
|
-
body: row.body,
|
|
5707
|
-
tags: (() => {
|
|
5708
|
-
try {
|
|
5709
|
-
const parsed = JSON.parse(row.tags);
|
|
5710
|
-
return Array.isArray(parsed) ? parsed.join(" ") : row.tags;
|
|
5711
|
-
} catch {
|
|
5712
|
-
return row.tags;
|
|
5713
|
-
}
|
|
5714
|
-
})()
|
|
5715
|
-
};
|
|
5663
|
+
const rows = await this.entryRepo.findMiniSearchRows(entityId);
|
|
5664
|
+
await this.indexStrategy.replaceEntity(entityId, rows.map(toIndexDoc));
|
|
5716
5665
|
}
|
|
5717
5666
|
_tieBreakSort(items) {
|
|
5718
5667
|
items.sort((a, b) => this._compareScoredRows(a, b));
|
|
@@ -5727,11 +5676,11 @@ var _SearchService = class _SearchService {
|
|
|
5727
5676
|
return a.id.localeCompare(b.id);
|
|
5728
5677
|
}
|
|
5729
5678
|
/**
|
|
5730
|
-
*
|
|
5731
|
-
* syncEntries changes: a discarded-and-re-added id moves to the end.
|
|
5732
|
-
* caller truncates these results to a limit, so which ids survive a
|
|
5733
|
-
* the boundary must not depend on write history. Re-sort exact
|
|
5734
|
-
* by id — the same final tie-break _compareScoredRows applies.
|
|
5679
|
+
* The keyword index breaks equal-score ties by internal insertion order,
|
|
5680
|
+
* which syncEntries changes: a discarded-and-re-added id moves to the end.
|
|
5681
|
+
* Every caller truncates these results to a limit, so which ids survive a
|
|
5682
|
+
* tie at the boundary must not depend on write history. Re-sort exact
|
|
5683
|
+
* score ties by id — the same final tie-break _compareScoredRows applies.
|
|
5735
5684
|
*/
|
|
5736
5685
|
_compareSearchResults(a, b) {
|
|
5737
5686
|
const scoreDiff = b.score - a.score;
|
|
@@ -5752,6 +5701,9 @@ _SearchService.MAX_VECTOR_CACHE_ENTITIES = 16;
|
|
|
5752
5701
|
*/
|
|
5753
5702
|
_SearchService.MAX_VECTOR_CACHE_FACTS_PER_ENTITY = 500;
|
|
5754
5703
|
var SearchService = _SearchService;
|
|
5704
|
+
function finiteResults(results) {
|
|
5705
|
+
return results.every((r) => Number.isFinite(r.score)) ? results : results.filter((r) => Number.isFinite(r.score));
|
|
5706
|
+
}
|
|
5755
5707
|
|
|
5756
5708
|
// src/services/JobManager.ts
|
|
5757
5709
|
var JobManager = class {
|