@equationalapplications/core-llm-wiki 7.9.0 → 7.9.2
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/dist/{chunk-J2TWKOEE.mjs → chunk-7FRLQ7ZO.mjs} +73 -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 +264 -127
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +196 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-Kb1uVj1E.d.mts → testing-Bf6etdUy.d.mts} +122 -23
- package/dist/{testing-Kb1uVj1E.d.ts → testing-Bf6etdUy.d.ts} +122 -23
- package/dist/testing.d.mts +1 -2
- package/dist/testing.d.ts +1 -2
- package/dist/testing.js +73 -131
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-J2TWKOEE.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-
|
|
2
|
-
export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityMaintenanceReport, l as EntityStatus, m as ExtractedFact, n as ExtractedFactEdge, o as ExtractedFactWithOntology, p as ExtractedTask, q as GraphTraversalOptions, r as GroundingConfig, H as HEAL_BATCH_SIZE, s as HEAL_RECHECK_MS, t as HOOK_TIMEOUT_MARKER, u as HealResult, I as IngestDocumentResult, L as LLMProvider, v as LibrarianConfig, w as LibrarianGateConfig, x as MaintenanceJob, y as MaintenanceStopReason, O as ONTOLOGY_BACKFILL_BATCH_SIZE, z as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, A as ONTOLOGY_BACKFILL_RECHECK_MS, B as OntologyBackfillResult, J as OntologyConfig, K as OntologyEdgeType, N as OntologyManifest, P as OntologyMode, Q as OntologyNodeType, T as OntologyPromptContext, U as OntologyUpdates, V as PendingMaintenance, X as PendingSourceStatus, Y as PromptOverrides, Z as PromptService, _ as PrunePartialFailureError, $ as ReembedResult, a0 as RunPendingMaintenanceOptions, a1 as RunPendingMaintenanceResult, a2 as SupersedeReplacement, a3 as VectorRanker, a4 as VectorRankerFallback, a5 as VectorRankerRankArgs, a6 as VectorRankerSemanticResult, a7 as WikiBusyError, a8 as WikiBusyOperation, a9 as WikiCheckpoint, aa as WikiConfig, ab as WikiDiagnostic, ac as WikiDiagnosticCode, ad as WikiDiagnosticDetail, ae as WikiDiagnosticOperation, af as WikiDiagnosticSeverity, ag as WikiDiagnosticTrigger, ah as WikiDraftNotFound, ai as WikiDuplicateHashError, aj as WikiEdge, ak as WikiEvent, al as WikiFact, am as WikiGraphNodeOwnershipConflict, an as WikiIngestEmptyError, ao as WikiInstructions, ap as WikiInvalidReadOptions, aq as WikiLintReport, ar as WikiMemoryTestAccess, as as WikiOutboxEvent, at as WikiParseError, au as WikiSourceRefHashCollision, av as WikiStrictOntologyViolation, aw as WikiSupersedeError, ax as WikiSupersedeReason, ay as WikiTask, az as WikiTransactionError, aA as validateManifest } from './testing-
|
|
1
|
+
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-Bf6etdUy.mjs';
|
|
2
|
+
export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityMaintenanceReport, l as EntityStatus, m as ExtractedFact, n as ExtractedFactEdge, o as ExtractedFactWithOntology, p as ExtractedTask, q as GraphTraversalOptions, r as GroundingConfig, H as HEAL_BATCH_SIZE, s as HEAL_RECHECK_MS, t as HOOK_TIMEOUT_MARKER, u as HealResult, I as IngestDocumentResult, L as LLMProvider, v as LibrarianConfig, w as LibrarianGateConfig, x as MaintenanceJob, y as MaintenanceStopReason, O as ONTOLOGY_BACKFILL_BATCH_SIZE, z as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, A as ONTOLOGY_BACKFILL_RECHECK_MS, B as OntologyBackfillResult, J as OntologyConfig, K as OntologyEdgeType, N as OntologyManifest, P as OntologyMode, Q as OntologyNodeType, T as OntologyPromptContext, U as OntologyUpdates, V as PendingMaintenance, X as PendingSourceStatus, Y as PromptOverrides, Z as PromptService, _ as PrunePartialFailureError, $ as ReembedResult, a0 as RunPendingMaintenanceOptions, a1 as RunPendingMaintenanceResult, a2 as SupersedeReplacement, a3 as VectorRanker, a4 as VectorRankerFallback, a5 as VectorRankerRankArgs, a6 as VectorRankerSemanticResult, a7 as WikiBusyError, a8 as WikiBusyOperation, a9 as WikiCheckpoint, aa as WikiConfig, ab as WikiDiagnostic, ac as WikiDiagnosticCode, ad as WikiDiagnosticDetail, ae as WikiDiagnosticOperation, af as WikiDiagnosticSeverity, ag as WikiDiagnosticTrigger, ah as WikiDraftNotFound, ai as WikiDuplicateHashError, aj as WikiEdge, ak as WikiEvent, al as WikiFact, am as WikiGraphNodeOwnershipConflict, an as WikiIngestEmptyError, ao as WikiInstructions, ap as WikiInvalidReadOptions, aq as WikiLintReport, ar as WikiMemoryTestAccess, as as WikiOutboxEvent, at as WikiParseError, au as WikiSourceRefHashCollision, av as WikiStrictOntologyViolation, aw as WikiSupersedeError, ax as WikiSupersedeReason, ay as WikiTask, az as WikiTransactionError, aA as validateManifest } from './testing-Bf6etdUy.mjs';
|
|
3
3
|
import { OkfFile } from '@equationalapplications/core-okf';
|
|
4
|
-
import 'minisearch';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Slices a string like `String.prototype.slice`, but clamps out-of-range
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-
|
|
2
|
-
export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityMaintenanceReport, l as EntityStatus, m as ExtractedFact, n as ExtractedFactEdge, o as ExtractedFactWithOntology, p as ExtractedTask, q as GraphTraversalOptions, r as GroundingConfig, H as HEAL_BATCH_SIZE, s as HEAL_RECHECK_MS, t as HOOK_TIMEOUT_MARKER, u as HealResult, I as IngestDocumentResult, L as LLMProvider, v as LibrarianConfig, w as LibrarianGateConfig, x as MaintenanceJob, y as MaintenanceStopReason, O as ONTOLOGY_BACKFILL_BATCH_SIZE, z as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, A as ONTOLOGY_BACKFILL_RECHECK_MS, B as OntologyBackfillResult, J as OntologyConfig, K as OntologyEdgeType, N as OntologyManifest, P as OntologyMode, Q as OntologyNodeType, T as OntologyPromptContext, U as OntologyUpdates, V as PendingMaintenance, X as PendingSourceStatus, Y as PromptOverrides, Z as PromptService, _ as PrunePartialFailureError, $ as ReembedResult, a0 as RunPendingMaintenanceOptions, a1 as RunPendingMaintenanceResult, a2 as SupersedeReplacement, a3 as VectorRanker, a4 as VectorRankerFallback, a5 as VectorRankerRankArgs, a6 as VectorRankerSemanticResult, a7 as WikiBusyError, a8 as WikiBusyOperation, a9 as WikiCheckpoint, aa as WikiConfig, ab as WikiDiagnostic, ac as WikiDiagnosticCode, ad as WikiDiagnosticDetail, ae as WikiDiagnosticOperation, af as WikiDiagnosticSeverity, ag as WikiDiagnosticTrigger, ah as WikiDraftNotFound, ai as WikiDuplicateHashError, aj as WikiEdge, ak as WikiEvent, al as WikiFact, am as WikiGraphNodeOwnershipConflict, an as WikiIngestEmptyError, ao as WikiInstructions, ap as WikiInvalidReadOptions, aq as WikiLintReport, ar as WikiMemoryTestAccess, as as WikiOutboxEvent, at as WikiParseError, au as WikiSourceRefHashCollision, av as WikiStrictOntologyViolation, aw as WikiSupersedeError, ax as WikiSupersedeReason, ay as WikiTask, az as WikiTransactionError, aA as validateManifest } from './testing-
|
|
1
|
+
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-Bf6etdUy.js';
|
|
2
|
+
export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityMaintenanceReport, l as EntityStatus, m as ExtractedFact, n as ExtractedFactEdge, o as ExtractedFactWithOntology, p as ExtractedTask, q as GraphTraversalOptions, r as GroundingConfig, H as HEAL_BATCH_SIZE, s as HEAL_RECHECK_MS, t as HOOK_TIMEOUT_MARKER, u as HealResult, I as IngestDocumentResult, L as LLMProvider, v as LibrarianConfig, w as LibrarianGateConfig, x as MaintenanceJob, y as MaintenanceStopReason, O as ONTOLOGY_BACKFILL_BATCH_SIZE, z as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, A as ONTOLOGY_BACKFILL_RECHECK_MS, B as OntologyBackfillResult, J as OntologyConfig, K as OntologyEdgeType, N as OntologyManifest, P as OntologyMode, Q as OntologyNodeType, T as OntologyPromptContext, U as OntologyUpdates, V as PendingMaintenance, X as PendingSourceStatus, Y as PromptOverrides, Z as PromptService, _ as PrunePartialFailureError, $ as ReembedResult, a0 as RunPendingMaintenanceOptions, a1 as RunPendingMaintenanceResult, a2 as SupersedeReplacement, a3 as VectorRanker, a4 as VectorRankerFallback, a5 as VectorRankerRankArgs, a6 as VectorRankerSemanticResult, a7 as WikiBusyError, a8 as WikiBusyOperation, a9 as WikiCheckpoint, aa as WikiConfig, ab as WikiDiagnostic, ac as WikiDiagnosticCode, ad as WikiDiagnosticDetail, ae as WikiDiagnosticOperation, af as WikiDiagnosticSeverity, ag as WikiDiagnosticTrigger, ah as WikiDraftNotFound, ai as WikiDuplicateHashError, aj as WikiEdge, ak as WikiEvent, al as WikiFact, am as WikiGraphNodeOwnershipConflict, an as WikiIngestEmptyError, ao as WikiInstructions, ap as WikiInvalidReadOptions, aq as WikiLintReport, ar as WikiMemoryTestAccess, as as WikiOutboxEvent, at as WikiParseError, au as WikiSourceRefHashCollision, av as WikiStrictOntologyViolation, aw as WikiSupersedeError, ax as WikiSupersedeReason, ay as WikiTask, az as WikiTransactionError, aA as validateManifest } from './testing-Bf6etdUy.js';
|
|
3
3
|
import { OkfFile } from '@equationalapplications/core-okf';
|
|
4
|
-
import 'minisearch';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Slices a string like `String.prototype.slice`, but clamps out-of-range
|
package/dist/index.js
CHANGED
|
@@ -3469,11 +3469,28 @@ function parseEmbedding(blob, text) {
|
|
|
3469
3469
|
return null;
|
|
3470
3470
|
}
|
|
3471
3471
|
|
|
3472
|
+
// src/utils/indexDoc.ts
|
|
3473
|
+
function toIndexDoc(row) {
|
|
3474
|
+
return {
|
|
3475
|
+
id: row.id,
|
|
3476
|
+
entity_id: row.entity_id,
|
|
3477
|
+
title: row.title,
|
|
3478
|
+
body: row.body,
|
|
3479
|
+
tags: (() => {
|
|
3480
|
+
try {
|
|
3481
|
+
const parsed = JSON.parse(row.tags);
|
|
3482
|
+
return Array.isArray(parsed) ? parsed.join(" ") : row.tags;
|
|
3483
|
+
} catch {
|
|
3484
|
+
return row.tags;
|
|
3485
|
+
}
|
|
3486
|
+
})()
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3472
3490
|
// src/services/SearchService.ts
|
|
3473
3491
|
var _SearchService = class _SearchService {
|
|
3474
|
-
constructor(entryRepo) {
|
|
3492
|
+
constructor(entryRepo, indexStrategy) {
|
|
3475
3493
|
this.entryRepo = entryRepo;
|
|
3476
|
-
this.miniSearchEntryIdsByEntity = /* @__PURE__ */ new Map();
|
|
3477
3494
|
this.vectorCache = /* @__PURE__ */ new Map();
|
|
3478
3495
|
/**
|
|
3479
3496
|
* Serializes rebuilds. `rebuildIndex` awaits a repository read between
|
|
@@ -3499,35 +3516,13 @@ var _SearchService = class _SearchService {
|
|
|
3499
3516
|
* its flag must outlive the turn (#233 review).
|
|
3500
3517
|
*/
|
|
3501
3518
|
this.staleEpochs = /* @__PURE__ */ new Map();
|
|
3502
|
-
this.
|
|
3503
|
-
}
|
|
3504
|
-
/**
|
|
3505
|
-
* A fresh index with the production options. clearAll() swaps one in because
|
|
3506
|
-
* MiniSearch.removeAll() empties the index but leaves dirtCount (and its
|
|
3507
|
-
* vacuum bookkeeping) at its old value, which would trip syncEntries'
|
|
3508
|
-
* conditional vacuum early after a clear.
|
|
3509
|
-
*/
|
|
3510
|
-
createMiniSearch() {
|
|
3511
|
-
return new MiniSearch__default.default({
|
|
3512
|
-
fields: ["title", "body", "tags"],
|
|
3513
|
-
storeFields: ["entity_id"],
|
|
3514
|
-
// Vacuuming is driven explicitly at the end of each serialized rebuild
|
|
3515
|
-
// (see sync). Auto-vacuum fires on its own schedule, asynchronously with
|
|
3516
|
-
// respect to the caller, and traversing the tree mid-rebuild is what
|
|
3517
|
-
// threw the uncaught TypeError in MiniSearch.performVacuuming (#64).
|
|
3518
|
-
autoVacuum: false,
|
|
3519
|
-
searchOptions: {
|
|
3520
|
-
boost: { title: 2 },
|
|
3521
|
-
fuzzy: 0.2,
|
|
3522
|
-
prefix: true
|
|
3523
|
-
}
|
|
3524
|
-
});
|
|
3519
|
+
this.indexStrategy = indexStrategy;
|
|
3525
3520
|
}
|
|
3526
3521
|
/**
|
|
3527
3522
|
* Rebuilds the search index and clears the vector cache for a given entity.
|
|
3528
3523
|
* A direct replacement for manually syncing state after a DB transaction.
|
|
3529
3524
|
*
|
|
3530
|
-
* Rebuilds are serialized per instance and never reject: the
|
|
3525
|
+
* Rebuilds are serialized per instance and never reject: the keyword index
|
|
3531
3526
|
* is a rebuildable cache over SQLite, so degraded keyword search is the
|
|
3532
3527
|
* correct failure mode and killing the host process is not.
|
|
3533
3528
|
*/
|
|
@@ -3536,19 +3531,21 @@ var _SearchService = class _SearchService {
|
|
|
3536
3531
|
try {
|
|
3537
3532
|
try {
|
|
3538
3533
|
const epochsBefore = new Map(this.staleEpochs);
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
this.staleEntities.delete(entityId);
|
|
3543
|
-
}
|
|
3544
|
-
} else {
|
|
3534
|
+
if (entityId === void 0) {
|
|
3535
|
+
const rows = await this.entryRepo.findMiniSearchRows();
|
|
3536
|
+
await this.indexStrategy.replaceAll(rows.map(toIndexDoc));
|
|
3545
3537
|
for (const id of [...this.staleEntities]) {
|
|
3546
3538
|
if ((this.staleEpochs.get(id) ?? 0) === (epochsBefore.get(id) ?? 0)) {
|
|
3547
3539
|
this.staleEntities.delete(id);
|
|
3548
3540
|
}
|
|
3549
3541
|
}
|
|
3542
|
+
} else {
|
|
3543
|
+
await this.rebuildIndex(entityId);
|
|
3544
|
+
if ((this.staleEpochs.get(entityId) ?? 0) === (epochsBefore.get(entityId) ?? 0)) {
|
|
3545
|
+
this.staleEntities.delete(entityId);
|
|
3546
|
+
}
|
|
3550
3547
|
}
|
|
3551
|
-
await this.
|
|
3548
|
+
await this.indexStrategy.vacuum?.();
|
|
3552
3549
|
} finally {
|
|
3553
3550
|
this.evictCache(entityId);
|
|
3554
3551
|
}
|
|
@@ -3573,27 +3570,20 @@ var _SearchService = class _SearchService {
|
|
|
3573
3570
|
*/
|
|
3574
3571
|
async syncEntries(entityId, ids) {
|
|
3575
3572
|
const uniqueIds = [...new Set(ids)];
|
|
3576
|
-
|
|
3573
|
+
const indexed = this.indexStrategy.hasIndexedEntity?.(entityId);
|
|
3574
|
+
if (uniqueIds.length === 0 && !this.staleEntities.has(entityId) && indexed === true) {
|
|
3577
3575
|
return this.syncChain;
|
|
3578
3576
|
}
|
|
3579
3577
|
const work = this.syncChain.then(async () => {
|
|
3580
3578
|
try {
|
|
3581
3579
|
try {
|
|
3582
3580
|
const epochsBefore = new Map(this.staleEpochs);
|
|
3583
|
-
const needsRebuild = () => this.staleEntities.has(entityId) ||
|
|
3581
|
+
const needsRebuild = () => this.staleEntities.has(entityId) || this.indexStrategy.hasIndexedEntity?.(entityId) !== true;
|
|
3584
3582
|
if (!needsRebuild()) {
|
|
3585
3583
|
const rows = await this.entryRepo.findMiniSearchRowsByIds(entityId, uniqueIds);
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
if (tracked.delete(id) && this.miniSearch.has(id)) this.miniSearch.discard(id);
|
|
3590
|
-
}
|
|
3591
|
-
const documents = rows.map((row) => this.normalizeMiniSearchRow(row));
|
|
3592
|
-
if (documents.length > 0) this.miniSearch.addAll(documents);
|
|
3593
|
-
for (const document of documents) tracked.add(document.id);
|
|
3594
|
-
if (this.miniSearch.dirtCount > 0) {
|
|
3595
|
-
await this.miniSearch.vacuum();
|
|
3596
|
-
}
|
|
3584
|
+
if (!this.staleEntities.has(entityId)) {
|
|
3585
|
+
await this.indexStrategy.replace(entityId, uniqueIds, rows.map(toIndexDoc));
|
|
3586
|
+
await this.indexStrategy.vacuum?.();
|
|
3597
3587
|
return;
|
|
3598
3588
|
}
|
|
3599
3589
|
}
|
|
@@ -3601,7 +3591,7 @@ var _SearchService = class _SearchService {
|
|
|
3601
3591
|
if ((this.staleEpochs.get(entityId) ?? 0) === (epochsBefore.get(entityId) ?? 0)) {
|
|
3602
3592
|
this.staleEntities.delete(entityId);
|
|
3603
3593
|
}
|
|
3604
|
-
await this.
|
|
3594
|
+
await this.indexStrategy.vacuum?.();
|
|
3605
3595
|
} finally {
|
|
3606
3596
|
this.evictCache(entityId);
|
|
3607
3597
|
}
|
|
@@ -3645,39 +3635,28 @@ var _SearchService = class _SearchService {
|
|
|
3645
3635
|
/**
|
|
3646
3636
|
* Fully resets the search service.
|
|
3647
3637
|
*/
|
|
3648
|
-
clearAll() {
|
|
3638
|
+
async clearAll() {
|
|
3649
3639
|
this.vectorCache.clear();
|
|
3650
|
-
|
|
3651
|
-
this.miniSearchEntryIdsByEntity.clear();
|
|
3640
|
+
await this.indexStrategy.replaceAll([]);
|
|
3652
3641
|
this.staleEntities.clear();
|
|
3653
3642
|
this.staleEpochs.clear();
|
|
3654
3643
|
}
|
|
3655
3644
|
/**
|
|
3656
|
-
* Executes a keyword search against the active
|
|
3645
|
+
* Executes a keyword search against the active index strategy.
|
|
3657
3646
|
*/
|
|
3658
|
-
searchKeyword(query, entityIds, limit) {
|
|
3659
|
-
const
|
|
3660
|
-
const results = this.miniSearch.search(query, {
|
|
3661
|
-
filter: (r) => entityIdSet.has(r.entity_id),
|
|
3662
|
-
combineWith: "OR"
|
|
3663
|
-
});
|
|
3647
|
+
async searchKeyword(query, entityIds, limit) {
|
|
3648
|
+
const results = finiteResults(await this.indexStrategy.search(query, { entityIds, limit }));
|
|
3664
3649
|
return results.sort((a, b) => this._compareSearchResults(a, b)).slice(0, limit);
|
|
3665
3650
|
}
|
|
3666
3651
|
/**
|
|
3667
|
-
* Pre-fetches
|
|
3652
|
+
* Pre-fetches keyword scores for candidate hydration, used during hybrid weighting.
|
|
3668
3653
|
*/
|
|
3669
|
-
|
|
3670
|
-
const
|
|
3671
|
-
|
|
3672
|
-
filter: (r) => entityIdSet.has(r.entity_id),
|
|
3673
|
-
combineWith: "OR"
|
|
3674
|
-
}).sort((a, b) => this._compareSearchResults(a, b));
|
|
3675
|
-
if (preFilterLimit !== void 0) {
|
|
3676
|
-
results = results.slice(0, preFilterLimit);
|
|
3677
|
-
}
|
|
3654
|
+
async getKeywordScores(query, entityIds, preFilterLimit) {
|
|
3655
|
+
const opts = preFilterLimit !== void 0 ? { entityIds, limit: preFilterLimit, preFilterLimit } : { entityIds, limit: Number.MAX_SAFE_INTEGER };
|
|
3656
|
+
const results = finiteResults(await this.indexStrategy.search(query, opts));
|
|
3678
3657
|
if (results.length === 0) return /* @__PURE__ */ new Map();
|
|
3679
|
-
const
|
|
3680
|
-
return new Map(results.map((r) => [r.id, r.score /
|
|
3658
|
+
const maxScore = Math.max(1, results[0]?.score ?? 1);
|
|
3659
|
+
return new Map(results.map((r) => [r.id, r.score / maxScore]));
|
|
3681
3660
|
}
|
|
3682
3661
|
/**
|
|
3683
3662
|
* Score candidate rows using in-process JS cosine similarity.
|
|
@@ -3739,53 +3718,16 @@ var _SearchService = class _SearchService {
|
|
|
3739
3718
|
return scored.slice(0, limit);
|
|
3740
3719
|
}
|
|
3741
3720
|
// --- Internal Index Management ---
|
|
3721
|
+
/**
|
|
3722
|
+
* Rebuild a single entity's index from scratch. Reads every row for
|
|
3723
|
+
* `entityId` from the repository (already filtered by `deleted_at IS NULL`)
|
|
3724
|
+
* and hands the lot to `indexStrategy.replaceEntity`, which owns the
|
|
3725
|
+
* drop-then-add bookkeeping so callers don't need to know the strategy's
|
|
3726
|
+
* id-tracking shape.
|
|
3727
|
+
*/
|
|
3742
3728
|
async rebuildIndex(entityId) {
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
const previousIds = this.miniSearchEntryIdsByEntity.get(entityId);
|
|
3746
|
-
if (previousIds) {
|
|
3747
|
-
for (const id of previousIds) {
|
|
3748
|
-
this.miniSearch.discard(id);
|
|
3749
|
-
}
|
|
3750
|
-
}
|
|
3751
|
-
const documents2 = rows2.map((row) => this.normalizeMiniSearchRow(row));
|
|
3752
|
-
if (documents2.length > 0) {
|
|
3753
|
-
this.miniSearch.addAll(documents2);
|
|
3754
|
-
}
|
|
3755
|
-
this.miniSearchEntryIdsByEntity.set(
|
|
3756
|
-
entityId,
|
|
3757
|
-
new Set(documents2.map((document) => document.id))
|
|
3758
|
-
);
|
|
3759
|
-
return;
|
|
3760
|
-
}
|
|
3761
|
-
const rows = await this.entryRepo.findMiniSearchRows();
|
|
3762
|
-
this.miniSearch.removeAll();
|
|
3763
|
-
this.miniSearchEntryIdsByEntity.clear();
|
|
3764
|
-
const documents = rows.map((row) => this.normalizeMiniSearchRow(row));
|
|
3765
|
-
if (documents.length > 0) {
|
|
3766
|
-
this.miniSearch.addAll(documents);
|
|
3767
|
-
}
|
|
3768
|
-
for (const document of documents) {
|
|
3769
|
-
const ids = this.miniSearchEntryIdsByEntity.get(document.entity_id) ?? /* @__PURE__ */ new Set();
|
|
3770
|
-
ids.add(document.id);
|
|
3771
|
-
this.miniSearchEntryIdsByEntity.set(document.entity_id, ids);
|
|
3772
|
-
}
|
|
3773
|
-
}
|
|
3774
|
-
normalizeMiniSearchRow(row) {
|
|
3775
|
-
return {
|
|
3776
|
-
id: row.id,
|
|
3777
|
-
entity_id: row.entity_id,
|
|
3778
|
-
title: row.title,
|
|
3779
|
-
body: row.body,
|
|
3780
|
-
tags: (() => {
|
|
3781
|
-
try {
|
|
3782
|
-
const parsed = JSON.parse(row.tags);
|
|
3783
|
-
return Array.isArray(parsed) ? parsed.join(" ") : row.tags;
|
|
3784
|
-
} catch {
|
|
3785
|
-
return row.tags;
|
|
3786
|
-
}
|
|
3787
|
-
})()
|
|
3788
|
-
};
|
|
3729
|
+
const rows = await this.entryRepo.findMiniSearchRows(entityId);
|
|
3730
|
+
await this.indexStrategy.replaceEntity(entityId, rows.map(toIndexDoc));
|
|
3789
3731
|
}
|
|
3790
3732
|
_tieBreakSort(items) {
|
|
3791
3733
|
items.sort((a, b) => this._compareScoredRows(a, b));
|
|
@@ -3800,11 +3742,11 @@ var _SearchService = class _SearchService {
|
|
|
3800
3742
|
return a.id.localeCompare(b.id);
|
|
3801
3743
|
}
|
|
3802
3744
|
/**
|
|
3803
|
-
*
|
|
3804
|
-
* syncEntries changes: a discarded-and-re-added id moves to the end.
|
|
3805
|
-
* caller truncates these results to a limit, so which ids survive a
|
|
3806
|
-
* the boundary must not depend on write history. Re-sort exact
|
|
3807
|
-
* by id — the same final tie-break _compareScoredRows applies.
|
|
3745
|
+
* The keyword index breaks equal-score ties by internal insertion order,
|
|
3746
|
+
* which syncEntries changes: a discarded-and-re-added id moves to the end.
|
|
3747
|
+
* Every caller truncates these results to a limit, so which ids survive a
|
|
3748
|
+
* tie at the boundary must not depend on write history. Re-sort exact
|
|
3749
|
+
* score ties by id — the same final tie-break _compareScoredRows applies.
|
|
3808
3750
|
*/
|
|
3809
3751
|
_compareSearchResults(a, b) {
|
|
3810
3752
|
const scoreDiff = b.score - a.score;
|
|
@@ -3825,6 +3767,198 @@ _SearchService.MAX_VECTOR_CACHE_ENTITIES = 16;
|
|
|
3825
3767
|
*/
|
|
3826
3768
|
_SearchService.MAX_VECTOR_CACHE_FACTS_PER_ENTITY = 500;
|
|
3827
3769
|
var SearchService = _SearchService;
|
|
3770
|
+
function finiteResults(results) {
|
|
3771
|
+
return results.every((r) => Number.isFinite(r.score)) ? results : results.filter((r) => Number.isFinite(r.score));
|
|
3772
|
+
}
|
|
3773
|
+
var MiniSearchIndexStrategy = class {
|
|
3774
|
+
constructor() {
|
|
3775
|
+
/**
|
|
3776
|
+
* Per-entity id set. `replaceEntity()` and `hasIndexedEntity()` read it;
|
|
3777
|
+
* `addDocuments()` and `discardIds()` keep it in sync. `SearchService` does
|
|
3778
|
+
* not see this map; it only sees `hasIndexedEntity`. The previous
|
|
3779
|
+
* `miniSearchEntryIdsByEntity` lived on `SearchService`.
|
|
3780
|
+
*/
|
|
3781
|
+
this.entryIdsByEntity = /* @__PURE__ */ new Map();
|
|
3782
|
+
/**
|
|
3783
|
+
* Reverse of `entryIdsByEntity`. `replace(entityId, ids, …)` uses it to
|
|
3784
|
+
* decide which ids are owned by `entityId` (the only safe membership test
|
|
3785
|
+
* — a rebuild that failed between its discard pass and the set replacement
|
|
3786
|
+
* can leave the forward set claiming ids the MiniSearch instance does not
|
|
3787
|
+
* hold). The pre-extraction `syncEntries` deleted from one set per id, not
|
|
3788
|
+
* from every entity's set.
|
|
3789
|
+
*/
|
|
3790
|
+
this.entityIdById = /* @__PURE__ */ new Map();
|
|
3791
|
+
this.index = this.createIndex();
|
|
3792
|
+
}
|
|
3793
|
+
/**
|
|
3794
|
+
* Build a fresh MiniSearch instance with the project's index options.
|
|
3795
|
+
* Called from the constructor and from `replaceAll`. We do not use
|
|
3796
|
+
* `removeAll()` on an existing instance because that empties the index but
|
|
3797
|
+
* leaves `dirtCount` and the vacuum bookkeeping intact, which would trip
|
|
3798
|
+
* `syncEntries`' conditional vacuum early after a clear.
|
|
3799
|
+
*/
|
|
3800
|
+
createIndex() {
|
|
3801
|
+
return new MiniSearch__default.default({
|
|
3802
|
+
fields: ["title", "body", "tags"],
|
|
3803
|
+
storeFields: ["entity_id"],
|
|
3804
|
+
// Vacuuming is driven explicitly at the end of each serialized rebuild
|
|
3805
|
+
// (see SearchService.syncEntries). Auto-vacuum fires on its own
|
|
3806
|
+
// schedule, asynchronously with respect to the caller, and traversing
|
|
3807
|
+
// the tree mid-rebuild is what threw the uncaught TypeError in
|
|
3808
|
+
// MiniSearch.performVacuuming (#64).
|
|
3809
|
+
autoVacuum: false,
|
|
3810
|
+
searchOptions: {
|
|
3811
|
+
boost: { title: 2 },
|
|
3812
|
+
fuzzy: 0.2,
|
|
3813
|
+
prefix: true
|
|
3814
|
+
}
|
|
3815
|
+
});
|
|
3816
|
+
}
|
|
3817
|
+
/**
|
|
3818
|
+
* Incremental sync. Removes only ids currently tracked under `entityId`
|
|
3819
|
+
* (other entities' docs are untouched), then upserts `documents` by id.
|
|
3820
|
+
* The same id appearing in both `ids` and `documents` is discarded first
|
|
3821
|
+
* so the upsert does not throw on a duplicate id.
|
|
3822
|
+
*
|
|
3823
|
+
* Every document must carry `entityId` as its `entity_id`; a mismatch is
|
|
3824
|
+
* rejected before the write mutates anything. A tracking-only call
|
|
3825
|
+
* (`replace(entityId, [], [])`) registers the entity as indexed, matching
|
|
3826
|
+
* the interface contract.
|
|
3827
|
+
*
|
|
3828
|
+
* Atomicity: never awaits between the discard pass and `addDocuments`, so
|
|
3829
|
+
* a concurrent `search()` sees the index wholly before or wholly after,
|
|
3830
|
+
* never half-updated. This is the precondition the pre-extraction
|
|
3831
|
+
* `syncEntries` kept with its "no await from here to `addAll`" comment.
|
|
3832
|
+
*/
|
|
3833
|
+
async replace(entityId, ids, documents) {
|
|
3834
|
+
assertOwnedBy(entityId, documents);
|
|
3835
|
+
this.discardIds(ids, entityId);
|
|
3836
|
+
if (!this.entryIdsByEntity.has(entityId)) this.entryIdsByEntity.set(entityId, /* @__PURE__ */ new Set());
|
|
3837
|
+
this.addDocuments(documents);
|
|
3838
|
+
}
|
|
3839
|
+
/**
|
|
3840
|
+
* Per-entity rebuild. Removes every id tracked under `entityId` (with the
|
|
3841
|
+
* `index.has(id)` guard so a stale tracking set cannot make `discard()`
|
|
3842
|
+
* throw), then writes `documents`. The entity stays registered as
|
|
3843
|
+
* indexed — even when `documents` is empty — so the next `syncEntries`
|
|
3844
|
+
* call can take the fast path. Every document must belong to `entityId`.
|
|
3845
|
+
*/
|
|
3846
|
+
async replaceEntity(entityId, documents) {
|
|
3847
|
+
assertOwnedBy(entityId, documents);
|
|
3848
|
+
const previous = this.entryIdsByEntity.get(entityId);
|
|
3849
|
+
if (previous) this.discardIds([...previous]);
|
|
3850
|
+
this.entryIdsByEntity.set(entityId, /* @__PURE__ */ new Set());
|
|
3851
|
+
this.addDocuments(documents);
|
|
3852
|
+
}
|
|
3853
|
+
/**
|
|
3854
|
+
* Global rebuild / clear. Replaces the MiniSearch instance and clears both
|
|
3855
|
+
* id maps, so `hasIndexedEntity` returns `false` for every entity afterwards.
|
|
3856
|
+
* `SearchService.clearAll()` calls `replaceAll([])`.
|
|
3857
|
+
*/
|
|
3858
|
+
async replaceAll(documents) {
|
|
3859
|
+
this.index = this.createIndex();
|
|
3860
|
+
this.entryIdsByEntity.clear();
|
|
3861
|
+
this.entityIdById.clear();
|
|
3862
|
+
this.addDocuments(documents);
|
|
3863
|
+
}
|
|
3864
|
+
/**
|
|
3865
|
+
* Best-match-first search over the documents whose `entity_id` is in
|
|
3866
|
+
* `options.entityIds`. `preFilterLimit` overrides `limit` (hybrid retrieval
|
|
3867
|
+
* uses this to over-fetch candidates before the `limit` cap). Scores are
|
|
3868
|
+
* raw BM25+ — `SearchService.getKeywordScores` and `searchKeyword` apply
|
|
3869
|
+
* any scaling, not the strategy.
|
|
3870
|
+
*/
|
|
3871
|
+
async search(query, options) {
|
|
3872
|
+
if (options.entityIds.length === 0) return [];
|
|
3873
|
+
const entityIdSet = new Set(options.entityIds);
|
|
3874
|
+
const limit = options.preFilterLimit ?? options.limit;
|
|
3875
|
+
const raw = this.index.search(query, {
|
|
3876
|
+
filter: (r) => entityIdSet.has(r.entity_id),
|
|
3877
|
+
combineWith: "OR"
|
|
3878
|
+
});
|
|
3879
|
+
raw.sort((a, b) => {
|
|
3880
|
+
const scoreDiff = b.score - a.score;
|
|
3881
|
+
if (!Number.isNaN(scoreDiff) && scoreDiff !== 0) return scoreDiff;
|
|
3882
|
+
return a.id.localeCompare(b.id);
|
|
3883
|
+
});
|
|
3884
|
+
return raw.slice(0, limit).map((r) => ({
|
|
3885
|
+
id: r.id,
|
|
3886
|
+
entity_id: r.entity_id,
|
|
3887
|
+
score: r.score
|
|
3888
|
+
}));
|
|
3889
|
+
}
|
|
3890
|
+
/**
|
|
3891
|
+
* Explicit vacuum. MiniSearch 7.2.0's `dirtCount` rule: search after an
|
|
3892
|
+
* un-vacuumed discard inverts the relative scores of term-sharing
|
|
3893
|
+
* documents at any index size. `SearchService.syncEntries` calls this
|
|
3894
|
+
* after a discard-bearing turn. No-op when `dirtCount === 0`.
|
|
3895
|
+
*/
|
|
3896
|
+
async vacuum() {
|
|
3897
|
+
if (this.index.dirtCount > 0) {
|
|
3898
|
+
await this.index.vacuum();
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3901
|
+
/**
|
|
3902
|
+
* `true` when `entityId` has been indexed at least once under the current
|
|
3903
|
+
* strategy state. Backed by `entryIdsByEntity.has(entityId)`, which is
|
|
3904
|
+
* kept in sync by `addDocuments`, `replaceEntity`, and `replaceAll`.
|
|
3905
|
+
*/
|
|
3906
|
+
hasIndexedEntity(entityId) {
|
|
3907
|
+
return this.entryIdsByEntity.has(entityId);
|
|
3908
|
+
}
|
|
3909
|
+
/**
|
|
3910
|
+
* Add `documents` to the MiniSearch instance and register them in
|
|
3911
|
+
* `entryIdsByEntity` and `entityIdById`. MiniSearch mutates documents
|
|
3912
|
+
* during `add`, so each doc is copied first. `add` throws on an id the
|
|
3913
|
+
* index already holds — `replace` and `replaceEntity` discard first for
|
|
3914
|
+
* that reason.
|
|
3915
|
+
*
|
|
3916
|
+
* Adds and registers one document at a time: if a duplicate id throws
|
|
3917
|
+
* part-way through, every document already in the index is tracked, so
|
|
3918
|
+
* the next rebuild can discard it instead of failing on it again. This is
|
|
3919
|
+
* the precondition the per-turn recovery path relies on (#258 review).
|
|
3920
|
+
*/
|
|
3921
|
+
addDocuments(documents) {
|
|
3922
|
+
for (const d of documents) {
|
|
3923
|
+
const doc = { ...d };
|
|
3924
|
+
this.index.add(doc);
|
|
3925
|
+
const set = this.entryIdsByEntity.get(doc.entity_id) ?? /* @__PURE__ */ new Set();
|
|
3926
|
+
set.add(doc.id);
|
|
3927
|
+
this.entryIdsByEntity.set(doc.entity_id, set);
|
|
3928
|
+
this.entityIdById.set(doc.id, doc.entity_id);
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
/**
|
|
3932
|
+
* Discard `ids` from the MiniSearch instance and from both id maps, but
|
|
3933
|
+
* only for ids currently owned by `entityId` (the second argument). When
|
|
3934
|
+
* `entityId` is omitted (used by `replaceEntity` for the bulk rebuild
|
|
3935
|
+
* path), every id is discarded regardless of owning entity.
|
|
3936
|
+
*
|
|
3937
|
+
* `index.has(id)` is the membership test of record: a rebuild that failed
|
|
3938
|
+
* between its own discard pass and the set replacement can leave the
|
|
3939
|
+
* tracking set claiming ids the index no longer holds — `discard()` throws
|
|
3940
|
+
* on those, so we guard.
|
|
3941
|
+
*/
|
|
3942
|
+
discardIds(ids, entityId) {
|
|
3943
|
+
for (const id of ids) {
|
|
3944
|
+
const owning = this.entityIdById.get(id);
|
|
3945
|
+
if (owning === void 0) continue;
|
|
3946
|
+
if (entityId !== void 0 && owning !== entityId) continue;
|
|
3947
|
+
if (this.index.has(id)) this.index.discard(id);
|
|
3948
|
+
this.entryIdsByEntity.get(owning)?.delete(id);
|
|
3949
|
+
this.entityIdById.delete(id);
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
};
|
|
3953
|
+
function assertOwnedBy(entityId, documents) {
|
|
3954
|
+
for (const doc of documents) {
|
|
3955
|
+
if (doc.entity_id !== entityId) {
|
|
3956
|
+
throw new Error(
|
|
3957
|
+
`IndexStrategy write for entity ${entityId} got document ${doc.id} under entity ${doc.entity_id}`
|
|
3958
|
+
);
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3828
3962
|
|
|
3829
3963
|
// src/services/JobManager.ts
|
|
3830
3964
|
var JobManager = class {
|
|
@@ -6488,7 +6622,7 @@ async function gateCandidates(deps, ctx, candidates, cfg) {
|
|
|
6488
6622
|
}
|
|
6489
6623
|
}
|
|
6490
6624
|
if (!ranked) {
|
|
6491
|
-
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 }));
|
|
6625
|
+
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 }));
|
|
6492
6626
|
}
|
|
6493
6627
|
const facts = ranked.length > 0 ? await deps.entryRepo.findByIds(ranked.map((r) => r.id), [entityId]) : [];
|
|
6494
6628
|
const byId = new Map(facts.map((f) => [f.id, f]));
|
|
@@ -7931,7 +8065,7 @@ var MaintenanceService = class {
|
|
|
7931
8065
|
if (!query) return [];
|
|
7932
8066
|
const cached = cache?.get(query);
|
|
7933
8067
|
if (cached) return cached;
|
|
7934
|
-
const hits = this.searchService.searchKeyword(
|
|
8068
|
+
const hits = await this.searchService.searchKeyword(
|
|
7935
8069
|
query,
|
|
7936
8070
|
[entityId],
|
|
7937
8071
|
cap * HEAL_ANCHOR_SEARCH_OVERFETCH
|
|
@@ -9103,7 +9237,7 @@ var RetrievalService = class {
|
|
|
9103
9237
|
let miniSearchScores;
|
|
9104
9238
|
if (effectivePreFilterLimit !== void 0) {
|
|
9105
9239
|
populateCache = false;
|
|
9106
|
-
const preResults = this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, Number.MAX_SAFE_INTEGER).filter((r) => !excludedIds.has(r.id));
|
|
9240
|
+
const preResults = (await this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, Number.MAX_SAFE_INTEGER)).filter((r) => !excludedIds.has(r.id));
|
|
9107
9241
|
if (preResults.length === 0) {
|
|
9108
9242
|
candidateRows = null;
|
|
9109
9243
|
} else {
|
|
@@ -9130,7 +9264,7 @@ var RetrievalService = class {
|
|
|
9130
9264
|
candidateRows = this._withoutIds(await this.entryRepo.findWithEmbeddingsByEntityIds(scoredEntityIds), excludedIds);
|
|
9131
9265
|
}
|
|
9132
9266
|
if (weight !== void 0 && weight < 1) {
|
|
9133
|
-
miniSearchScores = this.searchService.
|
|
9267
|
+
miniSearchScores = await this.searchService.getKeywordScores(trimmedQuery, scoredEntityIds);
|
|
9134
9268
|
}
|
|
9135
9269
|
}
|
|
9136
9270
|
if (candidateRows === null) {
|
|
@@ -9373,7 +9507,7 @@ var RetrievalService = class {
|
|
|
9373
9507
|
const hasActiveFloorsKeywordFallback = sanitizedTierFloors !== void 0 && Object.values(sanitizedTierFloors).some((f) => f > 0);
|
|
9374
9508
|
const keywordOversampledLimit = hasActiveFloorsKeywordFallback ? Number.MAX_SAFE_INTEGER : padLimit(Math.max(maxResults * 2, maxResults + 50));
|
|
9375
9509
|
const preFilteredIds = effectivePreFilterLimit !== void 0 ? new Set(candidateRows.map((r) => r.id)) : void 0;
|
|
9376
|
-
const keywordResults = this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, keywordOversampledLimit);
|
|
9510
|
+
const keywordResults = await this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, keywordOversampledLimit);
|
|
9377
9511
|
const topResults = preFilteredIds === void 0 ? keywordResults : keywordResults.filter((r) => preFilteredIds.has(r.id));
|
|
9378
9512
|
const topResultIds = new Set(topResults.map((r) => r.id));
|
|
9379
9513
|
const candidateMap = new Map(candidateRows.filter((r) => topResultIds.has(r.id)).map((row) => [row.id, row]));
|
|
@@ -9476,7 +9610,7 @@ var RetrievalService = class {
|
|
|
9476
9610
|
if (!usedEmbed && scoredEntityIds.length > 0) {
|
|
9477
9611
|
const hasActiveFloors = sanitizedTierFloors !== void 0 && Object.values(sanitizedTierFloors).some((f) => f > 0);
|
|
9478
9612
|
const fallbackOversampledLimit = hasActiveFloors ? Number.MAX_SAFE_INTEGER : padLimit(Math.max(maxResults * 2, maxResults + 50));
|
|
9479
|
-
const results = this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, fallbackOversampledLimit).filter((r) => !excludedIds.has(r.id));
|
|
9613
|
+
const results = (await this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, fallbackOversampledLimit)).filter((r) => !excludedIds.has(r.id));
|
|
9480
9614
|
const candidates = results.map((r) => ({
|
|
9481
9615
|
id: r.id,
|
|
9482
9616
|
entity_id: r.entity_id,
|
|
@@ -10308,7 +10442,10 @@ var WikiMemory = class {
|
|
|
10308
10442
|
);
|
|
10309
10443
|
this.lintService = new LintService(this.lintRepo, this.ontologyService);
|
|
10310
10444
|
this.embeddingService = new EmbeddingService(this.db, this.options, this.entryRepo, this.metadataRepo);
|
|
10311
|
-
this.searchService = new SearchService(
|
|
10445
|
+
this.searchService = new SearchService(
|
|
10446
|
+
this.entryRepo,
|
|
10447
|
+
new MiniSearchIndexStrategy()
|
|
10448
|
+
);
|
|
10312
10449
|
this.temporalService = new TemporalService(this.db, this.options, this.entryRepo, this.searchService, this.embeddingService);
|
|
10313
10450
|
this.jobManager = new JobManager(this.prefix);
|
|
10314
10451
|
this.promptService = new PromptService(options.config?.prompts, resolveGrounding(options.config?.grounding));
|