@avantf/dsh-mem 0.6.0 → 0.6.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.
Files changed (34) hide show
  1. package/lib/client.js +1 -0
  2. package/lib/engine/mem/db/dao/chunks.d.ts +60 -4
  3. package/lib/engine/mem/db/dao/shared.d.ts +153 -0
  4. package/lib/engine/mem/dispatch.d.ts +19 -1
  5. package/lib/engine/mem/eval/index.d.ts +4 -0
  6. package/lib/engine/mem/index.d.ts +2 -0
  7. package/lib/engine/mem/runtime.d.ts +2 -2
  8. package/lib/engine/mem/store/entity_sweep.d.ts +121 -0
  9. package/lib/engine/mem/store/hybrid.d.ts +50 -0
  10. package/lib/engine/mem/store/knowledge.d.ts +116 -12
  11. package/lib/engine/mem/store/legs.d.ts +171 -0
  12. package/lib/engine/mem/store/lexical.d.ts +8 -0
  13. package/lib/engine/mem/store/memory.d.ts +84 -72
  14. package/lib/engine/mem/store/vector_repair.d.ts +248 -0
  15. package/lib/engine/mem/trustHeartbeat.d.ts +47 -0
  16. package/lib/engine/mem-contract/tools.d.ts +4 -0
  17. package/lib/engine/mem-contract/types.d.ts +37 -6
  18. package/lib/engine/mem-retrieval/adapters/local_reranker.d.ts +52 -0
  19. package/lib/engine/mem-retrieval/adapters/none_reranker.d.ts +10 -0
  20. package/lib/engine/mem-retrieval/rerank.d.ts +13 -0
  21. package/lib/index.js +1653 -703
  22. package/lib/interface-version.json +1 -1
  23. package/lib/types/envinit-bootstrap.d.ts +1 -1
  24. package/lib/types/envinit.d.ts +0 -3
  25. package/lib/types/envinit.d.ts.map +1 -1
  26. package/lib/types/index.d.ts.map +1 -1
  27. package/lib/types/interface_gate.d.ts +70 -0
  28. package/lib/types/interface_gate.d.ts.map +1 -1
  29. package/lib/types/provision.d.ts +6 -0
  30. package/lib/types/provision.d.ts.map +1 -1
  31. package/lib/types/remote.d.ts.map +1 -1
  32. package/lib/types/vectorMigration.d.ts +22 -18
  33. package/lib/types/vectorMigration.d.ts.map +1 -1
  34. package/package.json +5 -5
@@ -0,0 +1,248 @@
1
+ /**
2
+ * The ONE vector-space repair flow both stores run.
3
+ *
4
+ * Changing the embedding space (model, width, pooling, normalization, input window, weights) is a
5
+ * DATA MIGRATION: persisted vectors keep decoding but live in another model's coordinates, so the
6
+ * semantic leg must not serve them. `common.ts` owns the cheap DETECTION (`reportStaleVectors`); this
7
+ * module owns the REPAIR — a bounded, resumable, switchable loop that re-encodes the corpus in
8
+ * slices and yields the event loop between them.
9
+ *
10
+ * It is a template method implemented by COMPOSITION (AGENTS.md / the design note in
11
+ * `docs/vector-repair-shared-flow.md`): the skeleton lives here as free functions, each store
12
+ * supplies a {@link VectorRepairTarget} adapter. No common base class — the two stores are separate
13
+ * databases with separate DAOs, and a base class would be a structural rewrite of two hub files.
14
+ *
15
+ * What is shared, and therefore must never be copied back into `store/memory.ts` /
16
+ * `store/knowledge.ts`: the batch size, the `yieldToEventLoop` call, the stop / resume / no-progress
17
+ * rules, the `semantic.auto_migrate` decision, the `dry_run` split, the order invariant
18
+ * (unusable bytes leave first, then re-encode), the warmup policy and the four log kinds.
19
+ *
20
+ * What stays in the stores (correct differences, DESIGN §2.3): the DAO calls and row shapes, the
21
+ * `conflict_checked` re-queue on the memory side, the `content_hash` reuse and failure counting on
22
+ * the knowledge side, the HRR column, and which live index a row is added to.
23
+ *
24
+ * @module store/vector_repair
25
+ */
26
+ import type { AvantfLogger, VectorMigrationOutcome, VectorMigrationProgress, VectorsFixReport, VectorsFixStoreReport } from '../../mem-contract/index.js';
27
+ import type { VectorStore } from '../../mem-retrieval/index.js';
28
+ import { type StaleVectorCounts } from './common.js';
29
+ /** The two stores this flow can drive. */
30
+ export type VectorRepairStore = 'memory' | 'knowledge';
31
+ /**
32
+ * Rows one background vector-space migration slice may re-encode.
33
+ *
34
+ * Small on purpose: the point of batching is that a query arriving mid-migration waits for at most
35
+ * one ONNX forward pass batch, not for a whole corpus. At ~30 ms per bge-base-zh encode a batch of 16
36
+ * is well under a second of contested model time, and the event loop is yielded between batches
37
+ * (`yieldToEventLoop`). The value is a default, not a promise — `migrateVectorSlice` takes whatever
38
+ * the caller needs.
39
+ */
40
+ export declare const DEFAULT_VECTOR_MIGRATION_BATCH = 16;
41
+ /**
42
+ * What one store's persisted-vector scan found, before any write.
43
+ *
44
+ * `stale` and `space_stale` mirror the cheap detection counts (`StaleVectorCounts`); `missing` is
45
+ * "ACTIVE row with no persisted vector at all" — the third reason the semantic leg cannot use a row.
46
+ */
47
+ export interface VectorsClassification {
48
+ /** ACTIVE rows whose persisted vector has the wrong width (it cannot even be decoded). */
49
+ stale: number;
50
+ /** ACTIVE rows whose usable-width vector was recorded in another space. */
51
+ space_stale: number;
52
+ /** ACTIVE rows with no persisted vector at all. */
53
+ missing: number;
54
+ /**
55
+ * Ids whose unusable bytes must leave the store before a re-encode picks them up (the `limit`
56
+ * passed to {@link VectorRepairTarget.classifyVectors} is applied). Knowledge overwrites vectors
57
+ * in place, so it reports none.
58
+ */
59
+ dropIds: readonly number[];
60
+ /**
61
+ * Usable persisted vectors absent from the LIVE index, decoded and ready to re-add. Only stores
62
+ * whose diagnose surface tracks the live index report this (memory); knowledge rebuilds its index
63
+ * at open and keeps it in sync on every write, so it omits the property entirely.
64
+ */
65
+ unindexed?: readonly {
66
+ id: number;
67
+ vec: Float32Array;
68
+ }[];
69
+ }
70
+ /**
71
+ * One store's half of the repair flow — the "key methods" of the template.
72
+ *
73
+ * Every method is a PRIMITIVE the store can answer from its own DAO; none of them contains the
74
+ * loop, the batch size or the switch logic (those are in this module, once).
75
+ */
76
+ export interface VectorRepairTarget {
77
+ readonly store: VectorRepairStore;
78
+ /** The manual entry the stale-vector warning points at, as the operator would type it. */
79
+ readonly manualEntry: string;
80
+ /** The representation fingerprint this store writes into now. */
81
+ vectorSpace(): string;
82
+ /** Is the embedding model loaded RIGHT NOW? (Never warms — the flow owns the warmup policy.) */
83
+ semanticAvailable(): boolean;
84
+ /** The RAW `semantic.auto_migrate` value; the flow decides what it means (`!== false`). */
85
+ autoMigrate(): boolean | undefined;
86
+ /** Cheap `{ stale, space_stale, legacy? }` — blob LENGTHS only, never decodes. */
87
+ vectorSpaceHealth(): StaleVectorCounts;
88
+ /** Cheap count of ACTIVE rows with no persisted vector (part of `remaining`). */
89
+ missingVectorCount(): number;
90
+ /** One scan classifying what needs dropping and re-encoding; `limit` bounds `dropIds`. */
91
+ classifyVectors(limit: number): VectorsClassification;
92
+ /**
93
+ * Optional: put usable persisted vectors missing from the live index back into it, returning how
94
+ * many were added. Called with the slice of {@link VectorsClassification.unindexed} the current
95
+ * `limit` allows, so the flow does not re-scan the corpus for it.
96
+ */
97
+ reindexUsable?(rows: readonly {
98
+ id: number;
99
+ vec: Float32Array;
100
+ }[]): number;
101
+ /** Clear unusable bytes (table + live index); returns how many rows were actually cleared. */
102
+ dropVectors(ids: readonly number[]): number;
103
+ /** Encode + persist up to `limit` rows into the current space, one row isolated at a time. */
104
+ reencodeVectors(limit: number): Promise<{
105
+ encoded: number;
106
+ failed: number;
107
+ }>;
108
+ /** Optional: wait for the embedding model (explicit repair only; the background never waits). */
109
+ warmup?(): Promise<boolean>;
110
+ }
111
+ /** A persisted vector row as read back from a store, for the shared open-time load. */
112
+ export interface PersistedVectorRow {
113
+ id: number;
114
+ vec: Uint8Array | null;
115
+ embedding_model?: string | null;
116
+ }
117
+ /**
118
+ * Rebuild one store's live vstore from its persisted rows, count what is unusable in the current
119
+ * space, and say so once — the shared "open for business" step both stores used to write twice.
120
+ *
121
+ * The owning store's ONLY half is the row read (`facts.activeVectorRows()` /
122
+ * `chunks.vectorRows()`); the reload, the count and the loud warning are one implementation, so a
123
+ * change to what counts as stale cannot land on one store only (the incident this exists for: the
124
+ * memory store checked the SPACE while knowledge checked only the WIDTH, so a model swap mixed two
125
+ * spaces in one index until someone happened to run `kb_reindex`).
126
+ */
127
+ export declare function loadVectorIndex(opts: {
128
+ store: VectorRepairStore;
129
+ vstore: VectorStore;
130
+ rows: readonly PersistedVectorRow[];
131
+ space: string;
132
+ manualEntry: string;
133
+ }): StaleVectorCounts;
134
+ /** One row the shared encode flow should turn into a vector. */
135
+ export interface VectorEncodeRow {
136
+ id: number;
137
+ text: string;
138
+ }
139
+ /** One encoded row ready to be persisted. */
140
+ export interface EncodedVector {
141
+ id: number;
142
+ bytes: Buffer;
143
+ }
144
+ /**
145
+ * One store's half of {@link encodeAndPersist}: how to encode, where the live index is, and how a
146
+ * group of vectors is persisted.
147
+ */
148
+ export interface EncodeWriteTarget {
149
+ readonly store: VectorRepairStore;
150
+ /** The space recorded beside every persisted vector. */
151
+ readonly space: string;
152
+ /** One text → vector. Throwing skips that row (never the group). */
153
+ encode(text: string): Promise<Float32Array>;
154
+ /** Add a freshly encoded vector to THIS store's live index. */
155
+ add(id: number, vec: Float32Array): void;
156
+ /**
157
+ * Persist one group of encoded rows. Throwing fails the WHOLE group, which is what lets the store
158
+ * decide how to reconcile its live index (see {@link onWriteError}).
159
+ */
160
+ write(rows: readonly EncodedVector[]): void;
161
+ /** Rows per `write` call (default 1). Knowledge uses its measured `WRITE_BATCH`. */
162
+ readonly writeBatch?: number;
163
+ /** Called once per row whose encode (or live-index add) failed. */
164
+ onRowError?(row: VectorEncodeRow, error: unknown): void;
165
+ /** Called once per group whose `write` failed, with the rows that never reached the database. */
166
+ onWriteError?(rows: readonly EncodedVector[], error: unknown): void;
167
+ }
168
+ /**
169
+ * Encode rows one at a time, add each to the live index, and persist them in groups.
170
+ *
171
+ * The shared skeleton: serial encode (a MEASURED decision for chunks — a padded batched forward pass
172
+ * is 1.79x slower on real 53–550 character chunks), `add` right after a successful encode, one
173
+ * `write` call per `writeBatch` rows, per-row isolation of encode failures, per-group isolation of
174
+ * write failures, and the `{ encoded, failed }` count.
175
+ *
176
+ * What stays with the store: the backend call, the live index, the write statement, the replay of a
177
+ * failed group, and the summary log — the memory store logs per row and keeps a half-written index
178
+ * (documented as the benign direction for it), the knowledge store evicts the group so both sides
179
+ * agree that the vectors are missing.
180
+ */
181
+ export declare function encodeAndPersist(rows: readonly VectorEncodeRow[], target: EncodeWriteTarget): Promise<{
182
+ encoded: number;
183
+ failed: number;
184
+ }>;
185
+ /**
186
+ * ONE bounded slice of the repair: re-add unusable-but-readable vectors that the live index lost,
187
+ * drop the rows a re-encode has to replace, then encode up to `limit` missing/foreign rows.
188
+ *
189
+ * `limit` is what makes the SAME logic usable as a background migration: one call is a bounded unit
190
+ * of work the caller can yield between. The explicit fix passes no limit (the operator action drains
191
+ * everything); the background drive passes its batch size.
192
+ *
193
+ * The ORDER is an invariant: unusable bytes leave the table and the live index first, so a
194
+ * re-encode can pick them up and a process that dies mid-migration leaves at most one batch
195
+ * vector-less — exactly the `missing` rows the next run resumes on.
196
+ */
197
+ export declare function repairVectorSlice(target: VectorRepairTarget, opts: {
198
+ dryRun: boolean;
199
+ limit?: number;
200
+ }): Promise<{
201
+ report: VectorsFixStoreReport;
202
+ remaining: number;
203
+ }>;
204
+ /**
205
+ * ONE bounded slice of the background migration — the unit the drive (and the tests) step.
206
+ *
207
+ * Resumability is a property of the DATABASE, not of this process: every slice re-derives what is
208
+ * stale from the persisted width/space, so a restart simply continues where the last slice stopped.
209
+ */
210
+ export declare function migrateVectorSlice(target: VectorRepairTarget, batchSize?: number): Promise<VectorMigrationProgress>;
211
+ /** Options for the background drive; the four log kinds go to `log` (the host logger by default). */
212
+ export interface DriveVectorRepairOptions {
213
+ batchSize?: number;
214
+ /** Plugin unmount / runtime shutdown: stop at the next batch boundary. */
215
+ shouldStop?: () => boolean;
216
+ onProgress?: (progress: VectorMigrationOutcome) => void;
217
+ /** Log sink; `retrievalLogger()` (the host logger once the runtime installed it) when omitted. */
218
+ log?: AvantfLogger;
219
+ }
220
+ /**
221
+ * Drive the bounded background migration for one store until it is current, the model is
222
+ * unavailable, or `shouldStop()` turns true (plugin unmount / process shutdown). A batch FAILURE
223
+ * never rejects: it is logged and reported as `remaining > 0`, which is what makes the next
224
+ * heartbeat a retry. Never blocks the event loop for longer than one batch.
225
+ *
226
+ * Honours `semantic.auto_migrate` (default on) — the switch exists so a host that must not spend CPU
227
+ * on background re-encoding can leave the loud warning and the manual entry as the only path. The
228
+ * switch is read through the adapter so a new store cannot forget it.
229
+ */
230
+ export declare function driveVectorRepair(target: VectorRepairTarget, opts?: DriveVectorRepairOptions): Promise<VectorMigrationOutcome>;
231
+ /**
232
+ * Drive every store in order. A stop request keeps the drive from starting another store, but each
233
+ * store still answers with its snapshot (so the caller can report what is left everywhere).
234
+ */
235
+ export declare function driveVectorRepairs(targets: readonly VectorRepairTarget[], opts?: DriveVectorRepairOptions): Promise<VectorMigrationOutcome[]>;
236
+ /**
237
+ * The explicit, unbounded repair behind `mem_admin vectors_fix` / `avantf-mem vectors --fix`,
238
+ * covering one or both stores.
239
+ *
240
+ * `store` selects a single store (omitted = both); `dry_run` previews every count without writing —
241
+ * and without loading the model (so a preview also reports `would_warm`). The top-level
242
+ * `semantic_available` is AND over the selected stores: `false` means at least one store's repair
243
+ * could not encode anything.
244
+ */
245
+ export declare function vectorsFix(targets: Partial<Record<VectorRepairStore, VectorRepairTarget>>, opts: {
246
+ dryRun: boolean;
247
+ store?: VectorRepairStore;
248
+ }): Promise<VectorsFixReport>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The trust heartbeat: the interval beat that advances the active-day clock and performs the
3
+ * settle / forget / idle / purge sweeps (TRUST_MODEL.md §5), shared by the DSH plugin and the MCP
4
+ * server.
5
+ *
6
+ * The two surfaces used to install it separately, and the copies drifted in exactly the places a
7
+ * copy drifts: the wording of the failure line and the work each beat does after the tick. The tick
8
+ * itself — the one thing that MUST be identical, because it is the trust clock — is what lives
9
+ * here. The differences are data: {@link TrustHeartbeatOptions.onBeat} is the extra work (the plugin
10
+ * sweeps entities and retries the vector migration), {@link TrustHeartbeatOptions.tickFailed} is how
11
+ * that surface names a failed sweep.
12
+ *
13
+ * `heartbeatMinutes <= 0` is the caller's decision, not this function's: a surface that disables the
14
+ * beat also decides whether it logs the interval line.
15
+ *
16
+ * Zero dependencies beyond `setInterval` so it stays in the engine (the plugin's index and the MCP
17
+ * entry both consume it).
18
+ */
19
+ /** A single beat's worth of the trust clock, plus the two per-surface differences. */
20
+ export interface TrustHeartbeatOptions {
21
+ /** The store whose active-day clock advances on presence. */
22
+ readonly memory: {
23
+ trustTick(): void;
24
+ };
25
+ /** Where a failed sweep is reported. Never allowed to make the beat itself throw. */
26
+ readonly logger: {
27
+ warn(message: string): void;
28
+ };
29
+ /** Minutes between beats. The caller does not install the beat unless this is positive. */
30
+ readonly heartbeatMinutes: number;
31
+ /** Extra per-beat work, run after the tick and OUTSIDE its catch (a failure here is the caller's). */
32
+ readonly onBeat?: () => void;
33
+ /**
34
+ * How this surface names a failed tick, given the caught value's message. Optional so the default
35
+ * (`trust tick failed: …`) holds for a caller that has no opinion.
36
+ */
37
+ readonly tickFailed?: (message: string) => string;
38
+ }
39
+ /**
40
+ * Install the heartbeat and return its disposer.
41
+ *
42
+ * A `trustTick` that throws is warned about and swallowed: a failed sweep must never take the host
43
+ * or the server down, and it must not be invisible either — a trust clock that stopped advancing
44
+ * shows up much later as facts that never settle, forget or purge. The timer is `unref`'d where the
45
+ * runtime supports it, so it never holds a process open by itself.
46
+ */
47
+ export declare function installTrustHeartbeat(options: TrustHeartbeatOptions): () => void;
@@ -161,6 +161,10 @@ export declare const AdminUnion: z.ZodDiscriminatedUnion<[z.ZodObject<{
161
161
  }, z.core.$strip>, z.ZodObject<{
162
162
  action: z.ZodLiteral<"vectors_fix">;
163
163
  dry_run: z.ZodOptional<z.ZodBoolean>;
164
+ store: z.ZodOptional<z.ZodEnum<{
165
+ memory: "memory";
166
+ knowledge: "knowledge";
167
+ }>>;
164
168
  }, z.core.$strip>, z.ZodObject<{
165
169
  action: z.ZodLiteral<"contradict_check">;
166
170
  }, z.core.$strip>, z.ZodObject<{
@@ -507,22 +507,53 @@ export interface VectorMigrationOutcome extends VectorMigrationProgress {
507
507
  enabled: boolean;
508
508
  }
509
509
  /**
510
- * `mem_admin vectors_fix`: what a repair did, or — with `dry_run` — what it WOULD do.
510
+ * ONE store's part of a vector repair (`mem_admin vectors_fix`).
511
+ *
512
+ * The common subset (`stale` / `space_stale` / `dropped` / `encoded` / `failed` /
513
+ * `semantic_available`) is what both stores report; `missing` and `would_warm` are shared steps of
514
+ * the repair flow, and `unindexed` / `reindexed` are only meaningful to a store that tracks its live
515
+ * index (memory — knowledge rebuilds it at open and keeps it in sync on every write).
511
516
  *
512
517
  * `semantic_available` is "the model is loaded RIGHT NOW" (a dry run must not load it), so the
513
518
  * preview also carries `would_warm`: together they separate "unknown until you run it" from
514
519
  * "the warmup was attempted and failed".
515
520
  */
516
- export interface VectorsFixReport {
517
- missing: number;
521
+ export interface VectorsFixStoreReport {
522
+ /** ACTIVE rows whose persisted vector has the wrong width. */
518
523
  stale: number;
524
+ /** ACTIVE rows whose usable-width vector was recorded in another space. */
519
525
  space_stale: number;
520
- unindexed: number;
521
- reindexed: number;
526
+ /** ACTIVE rows with no persisted vector at all (what the repair has to encode). */
527
+ missing: number;
528
+ /** Rows whose unusable old-space bytes were cleared so a re-encode could replace them. */
522
529
  dropped: number;
523
- fixed: number;
530
+ /** Rows re-encoded into the current space by this repair. */
531
+ encoded: number;
532
+ /** Rows whose encode or write failed; they stay `missing` / `stale` for the next pass. */
533
+ failed: number;
534
+ /** The model is loaded right now. */
524
535
  semantic_available: boolean;
536
+ /** The model was NOT loaded at entry, so a real run would attempt a warmup. */
525
537
  would_warm: boolean;
538
+ /** Usable persisted vectors absent from the live index (memory only). */
539
+ unindexed?: number;
540
+ /** Usable persisted vectors put back into the live index by this repair (memory only). */
541
+ reindexed?: number;
542
+ }
543
+ /**
544
+ * `mem_admin vectors_fix`: what a repair did, or — with `dry_run` — what it WOULD do, per store.
545
+ *
546
+ * The report is per-store because one switch and one call now cover BOTH libraries (a model swap
547
+ * leaves memory and knowledge in the same state, and the repair used to exist for memory only).
548
+ * `store` on the request narrows the call to one library; the top-level `semantic_available` is the
549
+ * AND over the stores actually repaired.
550
+ */
551
+ export interface VectorsFixReport {
552
+ stores: {
553
+ memory?: VectorsFixStoreReport;
554
+ knowledge?: VectorsFixStoreReport;
555
+ };
556
+ semantic_available: boolean;
526
557
  dry_run: boolean;
527
558
  }
528
559
  /** `kb_manage ingest`: what one document produced. */
@@ -0,0 +1,52 @@
1
+ import type { Reranker } from '../interfaces.js';
2
+ import { type ModelEnv } from './local_bge.js';
3
+ /** One text-classification result: transformers.js yields `{label, score}`; tolerate a raw `{data}` tensor too. */
4
+ type ClassifyResult = {
5
+ label?: string;
6
+ score?: number;
7
+ data?: number[];
8
+ };
9
+ /** The injected pipeline surface: a batch of (query, document) pairs in, scores out. */
10
+ export type ClassifyFn = (inputs: [string, string][], opts?: Record<string, unknown>) => Promise<ClassifyResult[]>;
11
+ /** Injectable seam: tests supply a fake classifier instead of the transformers.js import. */
12
+ export type RerankerPipeFactory = (model: string, env: ModelEnv) => Promise<ClassifyFn>;
13
+ /** Never hand the classifier a degenerate document; below this the score is meaningless. */
14
+ export declare const MIN_DOC_TOKENS = 16;
15
+ /**
16
+ * Local cross-encoder reranker via `@huggingface/transformers` (`bge-reranker`).
17
+ * Lazily imported; `warmUp()` configures the mirror/cache and triggers a load.
18
+ * Degrades to identity order when the package/model is not available.
19
+ *
20
+ * Like {@link LocalBgeBackend}, a failed warmup is retryable through
21
+ * `ensureWarm()` rather than being final until the next restart.
22
+ */
23
+ export declare class LocalReranker implements Reranker {
24
+ readonly name = "bge_reranker";
25
+ private _available;
26
+ private _pipe;
27
+ private _warming;
28
+ private _lengthWarned;
29
+ private _window;
30
+ private readonly configuredMax;
31
+ private readonly model;
32
+ private readonly env;
33
+ private readonly pipeFactory;
34
+ private readonly gate;
35
+ constructor(model: string, env?: Partial<ModelEnv>, pipeFactory?: RerankerPipeFactory);
36
+ isAvailable(): boolean;
37
+ /** Fire-and-forget retry for call sites that only observe availability (see `warm_gate.ts`). */
38
+ ensureWarm(): void;
39
+ warmUp(): Promise<void>;
40
+ private _doWarmup;
41
+ private window;
42
+ /**
43
+ * Bound one document for a pair, given how much of the window the query already spends.
44
+ * Returns the document text unchanged when it fits.
45
+ */
46
+ private boundDocument;
47
+ rerank(query: string, candidates: {
48
+ id: number;
49
+ text: string;
50
+ }[]): Promise<number[]>;
51
+ }
52
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { Reranker } from '../interfaces.js';
2
+ /** `none` — reranking disabled (the default). Reports unavailable so callers skip the rerank pass entirely. */
3
+ export declare class NoneReranker implements Reranker {
4
+ readonly name = "none";
5
+ isAvailable(): boolean;
6
+ rerank(_query: string, candidates: {
7
+ id: number;
8
+ text: string;
9
+ }[]): Promise<number[]>;
10
+ }
@@ -0,0 +1,13 @@
1
+ import type { Reranker } from './interfaces.js';
2
+ /**
3
+ * The one rerank-and-reorder pass shared by every retrieval leg (memory search,
4
+ * knowledge search — the blocks were byte-identical and had already drifted once
5
+ * on the miss-sort sentinel).
6
+ *
7
+ * Contract: `reranker.rerank` returns candidate ids best-first; ids it omits sort
8
+ * last with their fused order preserved (stable sort). A disabled/unavailable
9
+ * reranker is a pass-through.
10
+ */
11
+ export declare function rerankHits<T extends {
12
+ id: number;
13
+ }>(reranker: Reranker, query: string, hits: T[], textOf: (id: number) => string): Promise<T[]>;