@memberjunction/search-engine 5.33.0 → 5.34.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.
Files changed (87) hide show
  1. package/dist/generic/BaseReRanker.d.ts +164 -0
  2. package/dist/generic/BaseReRanker.d.ts.map +1 -0
  3. package/dist/generic/BaseReRanker.js +209 -0
  4. package/dist/generic/BaseReRanker.js.map +1 -0
  5. package/dist/generic/EntitySearchProvider.d.ts +36 -4
  6. package/dist/generic/EntitySearchProvider.d.ts.map +1 -1
  7. package/dist/generic/EntitySearchProvider.js +95 -19
  8. package/dist/generic/EntitySearchProvider.js.map +1 -1
  9. package/dist/generic/FullTextSearchProvider.d.ts +2 -2
  10. package/dist/generic/FullTextSearchProvider.d.ts.map +1 -1
  11. package/dist/generic/FullTextSearchProvider.js +14 -3
  12. package/dist/generic/FullTextSearchProvider.js.map +1 -1
  13. package/dist/generic/ISearchProvider.d.ts +44 -2
  14. package/dist/generic/ISearchProvider.d.ts.map +1 -1
  15. package/dist/generic/ISearchProvider.js +35 -1
  16. package/dist/generic/ISearchProvider.js.map +1 -1
  17. package/dist/generic/NoopReRanker.d.ts +28 -0
  18. package/dist/generic/NoopReRanker.d.ts.map +1 -0
  19. package/dist/generic/NoopReRanker.js +49 -0
  20. package/dist/generic/NoopReRanker.js.map +1 -0
  21. package/dist/generic/ScopeTemplateRenderer.d.ts +36 -0
  22. package/dist/generic/ScopeTemplateRenderer.d.ts.map +1 -0
  23. package/dist/generic/ScopeTemplateRenderer.js +110 -0
  24. package/dist/generic/ScopeTemplateRenderer.js.map +1 -0
  25. package/dist/generic/SearchEngine.d.ts +154 -12
  26. package/dist/generic/SearchEngine.d.ts.map +1 -1
  27. package/dist/generic/SearchEngine.js +662 -39
  28. package/dist/generic/SearchEngine.js.map +1 -1
  29. package/dist/generic/SearchFusion.d.ts +40 -6
  30. package/dist/generic/SearchFusion.d.ts.map +1 -1
  31. package/dist/generic/SearchFusion.js +139 -18
  32. package/dist/generic/SearchFusion.js.map +1 -1
  33. package/dist/generic/StorageSearchProvider.d.ts +9 -2
  34. package/dist/generic/StorageSearchProvider.d.ts.map +1 -1
  35. package/dist/generic/StorageSearchProvider.js +44 -12
  36. package/dist/generic/StorageSearchProvider.js.map +1 -1
  37. package/dist/generic/VectorSearchProvider.d.ts +9 -2
  38. package/dist/generic/VectorSearchProvider.d.ts.map +1 -1
  39. package/dist/generic/VectorSearchProvider.js +83 -13
  40. package/dist/generic/VectorSearchProvider.js.map +1 -1
  41. package/dist/generic/search.types.d.ts +206 -0
  42. package/dist/generic/search.types.d.ts.map +1 -1
  43. package/dist/index.d.ts +13 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +18 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/permissions/SearchScopePermissionResolver.d.ts +109 -0
  48. package/dist/permissions/SearchScopePermissionResolver.d.ts.map +1 -0
  49. package/dist/permissions/SearchScopePermissionResolver.js +159 -0
  50. package/dist/permissions/SearchScopePermissionResolver.js.map +1 -0
  51. package/dist/providers/AzureAISearchProvider.d.ts +37 -0
  52. package/dist/providers/AzureAISearchProvider.d.ts.map +1 -0
  53. package/dist/providers/AzureAISearchProvider.js +180 -0
  54. package/dist/providers/AzureAISearchProvider.js.map +1 -0
  55. package/dist/providers/ElasticsearchSearchProvider.d.ts +43 -0
  56. package/dist/providers/ElasticsearchSearchProvider.d.ts.map +1 -0
  57. package/dist/providers/ElasticsearchSearchProvider.js +200 -0
  58. package/dist/providers/ElasticsearchSearchProvider.js.map +1 -0
  59. package/dist/providers/OpenSearchSearchProvider.d.ts +36 -0
  60. package/dist/providers/OpenSearchSearchProvider.d.ts.map +1 -0
  61. package/dist/providers/OpenSearchSearchProvider.js +167 -0
  62. package/dist/providers/OpenSearchSearchProvider.js.map +1 -0
  63. package/dist/providers/TypesenseSearchProvider.d.ts +36 -0
  64. package/dist/providers/TypesenseSearchProvider.d.ts.map +1 -0
  65. package/dist/providers/TypesenseSearchProvider.js +161 -0
  66. package/dist/providers/TypesenseSearchProvider.js.map +1 -0
  67. package/dist/rerankers/BGEReRanker.d.ts +57 -0
  68. package/dist/rerankers/BGEReRanker.d.ts.map +1 -0
  69. package/dist/rerankers/BGEReRanker.js +193 -0
  70. package/dist/rerankers/BGEReRanker.js.map +1 -0
  71. package/dist/rerankers/CohereReRanker.d.ts +65 -0
  72. package/dist/rerankers/CohereReRanker.d.ts.map +1 -0
  73. package/dist/rerankers/CohereReRanker.js +155 -0
  74. package/dist/rerankers/CohereReRanker.js.map +1 -0
  75. package/dist/rerankers/OpenAIReRanker.d.ts +62 -0
  76. package/dist/rerankers/OpenAIReRanker.d.ts.map +1 -0
  77. package/dist/rerankers/OpenAIReRanker.js +197 -0
  78. package/dist/rerankers/OpenAIReRanker.js.map +1 -0
  79. package/dist/rerankers/RerankerBudgetGuard.d.ts +54 -0
  80. package/dist/rerankers/RerankerBudgetGuard.d.ts.map +1 -0
  81. package/dist/rerankers/RerankerBudgetGuard.js +67 -0
  82. package/dist/rerankers/RerankerBudgetGuard.js.map +1 -0
  83. package/dist/rerankers/VoyageReRanker.d.ts +59 -0
  84. package/dist/rerankers/VoyageReRanker.d.ts.map +1 -0
  85. package/dist/rerankers/VoyageReRanker.js +184 -0
  86. package/dist/rerankers/VoyageReRanker.js.map +1 -0
  87. package/package.json +13 -8
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @fileoverview BGE local-model re-ranker (P2D.5).
3
+ *
4
+ * Self-hosted reranker for deployments that don't want to send candidate documents
5
+ * to a third-party API. Wraps `@xenova/transformers`' `pipeline('text-classification')`
6
+ * loaded with a Xenova-converted BGE reranker model (e.g. `Xenova/bge-reranker-base`,
7
+ * `Xenova/bge-reranker-large`, `Xenova/bge-reranker-v2-m3`).
8
+ *
9
+ * **Cost.** Zero — local model. Reports 0 cents to the budget guard.
10
+ *
11
+ * **Model loading.** Lazy: the model is downloaded on first use into the configured
12
+ * `TRANSFORMERS_CACHE_DIR` (or the transformers.js default). The model is NOT bundled
13
+ * in the npm package. Override the model and cache directory via:
14
+ * - `ScopeConfig.reRanker.config.model` — HuggingFace ID or local path
15
+ * - `ScopeConfig.reRanker.config.cacheDir` — override TRANSFORMERS_CACHE_DIR
16
+ *
17
+ * **Optional peer dep.** `@xenova/transformers` is in `optionalDependencies`. Loaded
18
+ * via dynamic import per CLAUDE.md rule #8 case 2 — consumers who don't want a
19
+ * local-model reranker don't pay the bundle cost.
20
+ *
21
+ * @module @memberjunction/search-engine
22
+ */
23
+ import { UserInfo } from '@memberjunction/core';
24
+ import { BaseReRanker } from '../generic/BaseReRanker.js';
25
+ import { SearchResultItem } from '../generic/search.types.js';
26
+ /**
27
+ * Local BGE reranker. Configure per scope via
28
+ * `SearchScope.ScopeConfig.reRanker.driverClass = 'BGEReRanker'`.
29
+ */
30
+ export declare class BGEReRanker extends BaseReRanker {
31
+ get DriverClass(): string;
32
+ get Name(): string;
33
+ get Version(): string;
34
+ /**
35
+ * No hard cap from the model itself, but practical memory limits apply. We cap at
36
+ * 5000 to match what fits comfortably in 16 GB RAM with `bge-reranker-base`.
37
+ */
38
+ GetMaxResultCount(): number;
39
+ /** Local model — no per-call charge. */
40
+ EstimateCostCents(_resultCount: number): number;
41
+ ReRank(query: string, candidates: SearchResultItem[], topN: number, _contextUser: UserInfo, config?: Record<string, unknown>): Promise<SearchResultItem[]>;
42
+ /** Subclasses can override to customize the candidate's text representation. */
43
+ protected buildText(item: SearchResultItem): string;
44
+ /**
45
+ * Normalize the various shapes transformers.js may return into a flat number[]
46
+ * with one score per input pair. Throws when the shape doesn't match.
47
+ */
48
+ protected extractScores(raw: unknown, expectedLength: number): number[];
49
+ }
50
+ /** Tree-shake prevention helper. */
51
+ export declare function LoadBGEReRanker(): void;
52
+ /**
53
+ * Test-only export: clear the per-model pipeline cache. Used by tests so each test
54
+ * can install its own mock pipeline.
55
+ */
56
+ export declare function __resetBGEPipelineCacheForTests(): void;
57
+ //# sourceMappingURL=BGEReRanker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BGEReRanker.d.ts","sourceRoot":"","sources":["../../src/rerankers/BGEReRanker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AA6D3D;;;GAGG;AACH,qBACa,WAAY,SAAQ,YAAY;IACzC,IAAW,WAAW,IAAI,MAAM,CAE/B;IACD,IAAoB,IAAI,IAAI,MAAM,CAEjC;IACD,IAAoB,OAAO,IAAI,MAAM,CAEpC;IAED;;;OAGG;IACa,iBAAiB,IAAI,MAAM;IAI3C,wCAAwC;IACxB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAIzC,MAAM,CACxB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,gBAAgB,EAAE,EAC9B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,QAAQ,EACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAiD9B,gFAAgF;IAChF,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM;IAKnD;;;OAGG;IACH,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE;CAqB1E;AAED,oCAAoC;AACpC,wBAAgB,eAAe,IAAI,IAAI,CAGtC;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,IAAI,CAGtD"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * @fileoverview BGE local-model re-ranker (P2D.5).
3
+ *
4
+ * Self-hosted reranker for deployments that don't want to send candidate documents
5
+ * to a third-party API. Wraps `@xenova/transformers`' `pipeline('text-classification')`
6
+ * loaded with a Xenova-converted BGE reranker model (e.g. `Xenova/bge-reranker-base`,
7
+ * `Xenova/bge-reranker-large`, `Xenova/bge-reranker-v2-m3`).
8
+ *
9
+ * **Cost.** Zero — local model. Reports 0 cents to the budget guard.
10
+ *
11
+ * **Model loading.** Lazy: the model is downloaded on first use into the configured
12
+ * `TRANSFORMERS_CACHE_DIR` (or the transformers.js default). The model is NOT bundled
13
+ * in the npm package. Override the model and cache directory via:
14
+ * - `ScopeConfig.reRanker.config.model` — HuggingFace ID or local path
15
+ * - `ScopeConfig.reRanker.config.cacheDir` — override TRANSFORMERS_CACHE_DIR
16
+ *
17
+ * **Optional peer dep.** `@xenova/transformers` is in `optionalDependencies`. Loaded
18
+ * via dynamic import per CLAUDE.md rule #8 case 2 — consumers who don't want a
19
+ * local-model reranker don't pay the bundle cost.
20
+ *
21
+ * @module @memberjunction/search-engine
22
+ */
23
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
24
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
25
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
26
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
27
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
28
+ };
29
+ import { RegisterClass } from '@memberjunction/global';
30
+ import { LogError } from '@memberjunction/core';
31
+ import { BaseReRanker } from '../generic/BaseReRanker.js';
32
+ /**
33
+ * Memoized loader for the transformers.js module. Same pattern as LocalEmbedding —
34
+ * a single dynamic import the first time, reused thereafter.
35
+ */
36
+ let transformersPromise = null;
37
+ function loadTransformers() {
38
+ if (!transformersPromise) {
39
+ transformersPromise = (async () => {
40
+ try {
41
+ // SearchEngine is ESM (`"type": "module"`), so a real dynamic import is
42
+ // safe here — no need for the `eval('import(...)')` workaround that
43
+ // packages-as-CJS use. This is also what allows tests to vi.mock().
44
+ const mod = await import('@xenova/transformers');
45
+ return mod;
46
+ }
47
+ catch (err) {
48
+ throw new Error(`BGEReRanker: '@xenova/transformers' is not installed. Add it to your project's dependencies if you intend to use the BGE local reranker. Underlying error: ${err instanceof Error ? err.message : String(err)}`);
49
+ }
50
+ })();
51
+ }
52
+ return transformersPromise;
53
+ }
54
+ /**
55
+ * Per-model pipeline cache. Keyed by `${modelId}|${cacheDir}` so the same process can
56
+ * host multiple BGE variants without thrashing.
57
+ */
58
+ const pipelineCache = new Map();
59
+ async function getPipeline(modelId, cacheDir) {
60
+ const key = `${modelId}|${cacheDir ?? ''}`;
61
+ let cached = pipelineCache.get(key);
62
+ if (!cached) {
63
+ cached = (async () => {
64
+ const transformers = await loadTransformers();
65
+ if (cacheDir)
66
+ transformers.env.cacheDir = cacheDir;
67
+ return transformers.pipeline('text-classification', modelId, { quantized: true });
68
+ })();
69
+ pipelineCache.set(key, cached);
70
+ }
71
+ return cached;
72
+ }
73
+ /**
74
+ * Local BGE reranker. Configure per scope via
75
+ * `SearchScope.ScopeConfig.reRanker.driverClass = 'BGEReRanker'`.
76
+ */
77
+ let BGEReRanker = class BGEReRanker extends BaseReRanker {
78
+ get DriverClass() {
79
+ return 'BGEReRanker';
80
+ }
81
+ get Name() {
82
+ return 'BGE';
83
+ }
84
+ get Version() {
85
+ return '1';
86
+ }
87
+ /**
88
+ * No hard cap from the model itself, but practical memory limits apply. We cap at
89
+ * 5000 to match what fits comfortably in 16 GB RAM with `bge-reranker-base`.
90
+ */
91
+ GetMaxResultCount() {
92
+ return 5000;
93
+ }
94
+ /** Local model — no per-call charge. */
95
+ EstimateCostCents(_resultCount) {
96
+ return 0;
97
+ }
98
+ async ReRank(query, candidates, topN, _contextUser, config) {
99
+ if (topN <= 0 || candidates.length === 0)
100
+ return [];
101
+ const modelId = config?.['model'] ?? 'Xenova/bge-reranker-base';
102
+ const cacheDir = config?.['cacheDir'];
103
+ let scoreFor;
104
+ try {
105
+ scoreFor = await getPipeline(modelId, cacheDir);
106
+ }
107
+ catch (err) {
108
+ LogError(`BGEReRanker: failed to load pipeline for "${modelId}": ${err instanceof Error ? err.message : String(err)}`);
109
+ // Fall back to a top-N slice when the local model can't be loaded.
110
+ return candidates.slice(0, topN);
111
+ }
112
+ try {
113
+ // For cross-encoder reranking we feed each candidate as a [query, doc] pair.
114
+ // transformers.js text-classification accepts an array of pairs — call once
115
+ // with all pairs to get one response per pair.
116
+ const pairs = candidates.map(c => [query, this.buildText(c)]);
117
+ const raw = await scoreFor(pairs);
118
+ // The pipeline returns either an array of `{label, score}` (one per pair) or
119
+ // an array of arrays when multi-label is enabled. Normalize to a flat array
120
+ // of scores. We treat `score` as relevance directly; for binary cross-encoders
121
+ // the model emits a logit-style score we use as-is for ranking purposes.
122
+ const scores = this.extractScores(raw, candidates.length);
123
+ const ranked = candidates
124
+ .map((c, i) => ({
125
+ item: c,
126
+ score: scores[i] ?? 0,
127
+ }))
128
+ .sort((a, b) => b.score - a.score)
129
+ .slice(0, topN)
130
+ .map(p => ({
131
+ ...p.item,
132
+ Score: p.score,
133
+ ScoreBreakdown: { ...p.item.ScoreBreakdown, ReRank: p.score },
134
+ }));
135
+ // Local model — no cost reported.
136
+ return ranked;
137
+ }
138
+ catch (err) {
139
+ LogError(`BGEReRanker: rerank failed for "${modelId}": ${err instanceof Error ? err.message : String(err)}`);
140
+ return candidates.slice(0, topN);
141
+ }
142
+ }
143
+ /** Subclasses can override to customize the candidate's text representation. */
144
+ buildText(item) {
145
+ const parts = [item.Title, item.Snippet].filter(p => p != null && p.length > 0);
146
+ return parts.join('\n');
147
+ }
148
+ /**
149
+ * Normalize the various shapes transformers.js may return into a flat number[]
150
+ * with one score per input pair. Throws when the shape doesn't match.
151
+ */
152
+ extractScores(raw, expectedLength) {
153
+ if (!Array.isArray(raw)) {
154
+ throw new Error('BGEReRanker: pipeline did not return an array');
155
+ }
156
+ const out = [];
157
+ for (const entry of raw) {
158
+ if (entry && typeof entry === 'object' && 'score' in entry && typeof entry.score === 'number') {
159
+ out.push(entry.score);
160
+ }
161
+ else if (Array.isArray(entry)) {
162
+ // Multi-label form — take the first label's score
163
+ const first = entry[0];
164
+ out.push(first && typeof first.score === 'number' ? first.score : 0);
165
+ }
166
+ else {
167
+ out.push(0);
168
+ }
169
+ }
170
+ if (out.length !== expectedLength) {
171
+ throw new Error(`BGEReRanker: pipeline returned ${out.length} scores for ${expectedLength} inputs`);
172
+ }
173
+ return out;
174
+ }
175
+ };
176
+ BGEReRanker = __decorate([
177
+ RegisterClass(BaseReRanker, 'BGEReRanker')
178
+ ], BGEReRanker);
179
+ export { BGEReRanker };
180
+ /** Tree-shake prevention helper. */
181
+ export function LoadBGEReRanker() {
182
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
183
+ const _ref = BGEReRanker;
184
+ }
185
+ /**
186
+ * Test-only export: clear the per-model pipeline cache. Used by tests so each test
187
+ * can install its own mock pipeline.
188
+ */
189
+ export function __resetBGEPipelineCacheForTests() {
190
+ pipelineCache.clear();
191
+ transformersPromise = null;
192
+ }
193
+ //# sourceMappingURL=BGEReRanker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BGEReRanker.js","sourceRoot":"","sources":["../../src/rerankers/BGEReRanker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @fileoverview Cohere Rerank API integration (P2D.2).
3
+ *
4
+ * Wraps Cohere's `rerank-v3.5` (English) and `rerank-multilingual-v3.0` endpoints
5
+ * for use as a SearchEngine re-ranker. Distinct from `@memberjunction/ai-cohere`'s
6
+ * `CohereReranker` which is purpose-built for memory-note rerank with a specific
7
+ * augmented prompt — scope search needs the raw query passed through unchanged
8
+ * for accurate semantic similarity.
9
+ *
10
+ * **Cost model.** Cohere bills per "search," where one search reranks up to 100
11
+ * documents. Above 100 docs, larger requests count as multiple searches.
12
+ * Pricing as of 2026-04: $2.00 per 1k searches → 0.2¢ / search.
13
+ *
14
+ * **API key resolution.** Uses `GetAIAPIKey('CohereLLM')` — same key the AI-layer
15
+ * Cohere reranker uses, sourced from the AIAPIKey registry (driver class
16
+ * `CohereLLM` → env var `AI_VENDOR_API_KEY__COHERELLM`).
17
+ *
18
+ * **Optional peer dependency.** `cohere-ai` is declared in `optionalDependencies`
19
+ * so SearchEngine consumers who don't use Cohere don't pay the bundle cost.
20
+ * Loaded via a dynamic import per CLAUDE.md rule #8 case 2 (optional peer).
21
+ *
22
+ * @module @memberjunction/search-engine
23
+ */
24
+ import { UserInfo } from '@memberjunction/core';
25
+ import { BaseReranker as AIBaseReranker } from '@memberjunction/ai';
26
+ import { BaseReRanker } from '../generic/BaseReRanker.js';
27
+ import { SearchResultItem } from '../generic/search.types.js';
28
+ /**
29
+ * Cohere `rerank-v3.5` re-ranker for SearchEngine. Configured per scope via
30
+ * `SearchScope.ScopeConfig.reRanker.driverClass = 'CohereReRanker'`.
31
+ *
32
+ * The model name can be overridden via `ScopeConfig.reRanker.config.model`
33
+ * (e.g. `'rerank-multilingual-v3.0'`).
34
+ */
35
+ export declare class CohereReRanker extends BaseReRanker {
36
+ get DriverClass(): string;
37
+ get Name(): string;
38
+ get Version(): string;
39
+ /**
40
+ * Cohere caps a single rerank call at 1000 documents. Above this, the SearchEngine
41
+ * should chunk (not implemented yet — most realistic candidate lists are <100).
42
+ */
43
+ GetMaxResultCount(): number;
44
+ /**
45
+ * Cohere bills per "search". 1 search reranks up to 100 documents; above 100,
46
+ * count as `ceil(N/100)` searches. As of 2026-04, $2.00 per 1k searches = 0.2¢
47
+ * per search. Override via `config.cents_per_search` if Cohere's pricing changes.
48
+ */
49
+ EstimateCostCents(resultCount: number): number;
50
+ protected getAIReranker(config: Record<string, unknown> | undefined, _contextUser: UserInfo): AIBaseReranker | null;
51
+ /**
52
+ * Override `ReRank` to record actual cost via the inherited `reportCost` helper
53
+ * after a successful Cohere call. Cohere bills per request (not per token), so
54
+ * the post-call cost equals the pre-call estimate — no separate measurement
55
+ * required.
56
+ */
57
+ ReRank(query: string, candidates: SearchResultItem[], topN: number, contextUser: UserInfo, config?: Record<string, unknown>): Promise<SearchResultItem[]>;
58
+ }
59
+ /**
60
+ * Tree-shake prevention helper. Call from a consumer's `public-api.ts` (or from
61
+ * `LoadCohereReRanker()` in a generated registration manifest) to guarantee the
62
+ * `@RegisterClass` side-effect runs.
63
+ */
64
+ export declare function LoadCohereReRanker(): void;
65
+ //# sourceMappingURL=CohereReRanker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CohereReRanker.d.ts","sourceRoot":"","sources":["../../src/rerankers/CohereReRanker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACH,YAAY,IAAI,cAAc,EAIjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAkE3D;;;;;;GAMG;AACH,qBACa,cAAe,SAAQ,YAAY;IAC5C,IAAW,WAAW,IAAI,MAAM,CAE/B;IACD,IAAoB,IAAI,IAAI,MAAM,CAEjC;IACD,IAAoB,OAAO,IAAI,MAAM,CAEpC;IAED;;;OAGG;IACa,iBAAiB,IAAI,MAAM;IAI3C;;;;OAIG;IACa,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;cAK3C,aAAa,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,YAAY,EAAE,QAAQ,GACvB,cAAc,GAAG,IAAI;IAUxB;;;;;OAKG;IACmB,MAAM,CACxB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,gBAAgB,EAAE,EAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,QAAQ,EACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAUjC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @fileoverview Cohere Rerank API integration (P2D.2).
3
+ *
4
+ * Wraps Cohere's `rerank-v3.5` (English) and `rerank-multilingual-v3.0` endpoints
5
+ * for use as a SearchEngine re-ranker. Distinct from `@memberjunction/ai-cohere`'s
6
+ * `CohereReranker` which is purpose-built for memory-note rerank with a specific
7
+ * augmented prompt — scope search needs the raw query passed through unchanged
8
+ * for accurate semantic similarity.
9
+ *
10
+ * **Cost model.** Cohere bills per "search," where one search reranks up to 100
11
+ * documents. Above 100 docs, larger requests count as multiple searches.
12
+ * Pricing as of 2026-04: $2.00 per 1k searches → 0.2¢ / search.
13
+ *
14
+ * **API key resolution.** Uses `GetAIAPIKey('CohereLLM')` — same key the AI-layer
15
+ * Cohere reranker uses, sourced from the AIAPIKey registry (driver class
16
+ * `CohereLLM` → env var `AI_VENDOR_API_KEY__COHERELLM`).
17
+ *
18
+ * **Optional peer dependency.** `cohere-ai` is declared in `optionalDependencies`
19
+ * so SearchEngine consumers who don't use Cohere don't pay the bundle cost.
20
+ * Loaded via a dynamic import per CLAUDE.md rule #8 case 2 (optional peer).
21
+ *
22
+ * @module @memberjunction/search-engine
23
+ */
24
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
25
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
26
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
27
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
28
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
29
+ };
30
+ import { RegisterClass } from '@memberjunction/global';
31
+ import { LogError } from '@memberjunction/core';
32
+ import { BaseReranker as AIBaseReranker, GetAIAPIKey, } from '@memberjunction/ai';
33
+ import { BaseReRanker } from '../generic/BaseReRanker.js';
34
+ /**
35
+ * Memoized loader for the Cohere SDK. The dynamic import is the **single** approved
36
+ * use of `import()` in this file (CLAUDE.md #8 case 2 — optional peer dep). Caching
37
+ * the resolved client constructor avoids paying the dynamic import cost on every
38
+ * Rerank call.
39
+ */
40
+ let cohereClientCtorPromise = null;
41
+ async function getCohereClientCtor() {
42
+ if (!cohereClientCtorPromise) {
43
+ cohereClientCtorPromise = (async () => {
44
+ try {
45
+ const mod = await import('cohere-ai');
46
+ return mod.CohereClient;
47
+ }
48
+ catch (err) {
49
+ throw new Error(`CohereReRanker: 'cohere-ai' is not installed. Add it to your project's dependencies if you intend to use the Cohere reranker. Underlying error: ${err instanceof Error ? err.message : String(err)}`);
50
+ }
51
+ })();
52
+ }
53
+ return cohereClientCtorPromise;
54
+ }
55
+ /**
56
+ * Inline AI-layer reranker that calls Cohere's `rerank` endpoint with the raw query
57
+ * (no enhanced prompt). Distinct from `@memberjunction/ai-cohere`'s `CohereReranker`
58
+ * which augments the query for memory-note semantics.
59
+ */
60
+ class CohereScopeAIReranker extends AIBaseReranker {
61
+ constructor(apiKey, modelName) {
62
+ super(apiKey, modelName);
63
+ this._clientPromise = getCohereClientCtor().then(Ctor => new Ctor({ token: this.apiKey }));
64
+ }
65
+ async doRerank(params) {
66
+ const client = await this._clientPromise;
67
+ const response = await client.rerank({
68
+ model: this._modelName,
69
+ query: params.query,
70
+ documents: params.documents.map(d => d.text),
71
+ topN: params.topK ?? params.documents.length,
72
+ returnDocuments: false,
73
+ });
74
+ return response.results.map((r, idx) => ({
75
+ id: params.documents[r.index].id,
76
+ relevanceScore: r.relevanceScore,
77
+ document: params.documents[r.index],
78
+ rank: idx,
79
+ }));
80
+ }
81
+ }
82
+ /**
83
+ * Cohere `rerank-v3.5` re-ranker for SearchEngine. Configured per scope via
84
+ * `SearchScope.ScopeConfig.reRanker.driverClass = 'CohereReRanker'`.
85
+ *
86
+ * The model name can be overridden via `ScopeConfig.reRanker.config.model`
87
+ * (e.g. `'rerank-multilingual-v3.0'`).
88
+ */
89
+ let CohereReRanker = class CohereReRanker extends BaseReRanker {
90
+ get DriverClass() {
91
+ return 'CohereReRanker';
92
+ }
93
+ get Name() {
94
+ return 'Cohere';
95
+ }
96
+ get Version() {
97
+ return '1';
98
+ }
99
+ /**
100
+ * Cohere caps a single rerank call at 1000 documents. Above this, the SearchEngine
101
+ * should chunk (not implemented yet — most realistic candidate lists are <100).
102
+ */
103
+ GetMaxResultCount() {
104
+ return 1000;
105
+ }
106
+ /**
107
+ * Cohere bills per "search". 1 search reranks up to 100 documents; above 100,
108
+ * count as `ceil(N/100)` searches. As of 2026-04, $2.00 per 1k searches = 0.2¢
109
+ * per search. Override via `config.cents_per_search` if Cohere's pricing changes.
110
+ */
111
+ EstimateCostCents(resultCount) {
112
+ const searches = Math.max(1, Math.ceil(resultCount / 100));
113
+ return searches * 0.2;
114
+ }
115
+ getAIReranker(config, _contextUser) {
116
+ const apiKey = GetAIAPIKey('CohereLLM');
117
+ if (!apiKey) {
118
+ LogError('CohereReRanker: no API key found for driver "CohereLLM" — set AI_VENDOR_API_KEY__COHERELLM or register an AIAPIKeys subclass.');
119
+ return null;
120
+ }
121
+ const modelName = config?.['model'] ?? 'rerank-v3.5';
122
+ return new CohereScopeAIReranker(apiKey, modelName);
123
+ }
124
+ /**
125
+ * Override `ReRank` to record actual cost via the inherited `reportCost` helper
126
+ * after a successful Cohere call. Cohere bills per request (not per token), so
127
+ * the post-call cost equals the pre-call estimate — no separate measurement
128
+ * required.
129
+ */
130
+ async ReRank(query, candidates, topN, contextUser, config) {
131
+ if (topN <= 0 || candidates.length === 0)
132
+ return [];
133
+ const result = await super.ReRank(query, candidates, topN, contextUser, config);
134
+ // Charge cost only when the call actually went out — when getAIReranker
135
+ // returns null, super.ReRank short-circuits to a slice and we shouldn't bill.
136
+ if (this.getAIReranker(config, contextUser)) {
137
+ this.reportCost(this.EstimateCostCents(candidates.length));
138
+ }
139
+ return result;
140
+ }
141
+ };
142
+ CohereReRanker = __decorate([
143
+ RegisterClass(BaseReRanker, 'CohereReRanker')
144
+ ], CohereReRanker);
145
+ export { CohereReRanker };
146
+ /**
147
+ * Tree-shake prevention helper. Call from a consumer's `public-api.ts` (or from
148
+ * `LoadCohereReRanker()` in a generated registration manifest) to guarantee the
149
+ * `@RegisterClass` side-effect runs.
150
+ */
151
+ export function LoadCohereReRanker() {
152
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
153
+ const _ref = CohereReRanker;
154
+ }
155
+ //# sourceMappingURL=CohereReRanker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CohereReRanker.js","sourceRoot":"","sources":["../../src/rerankers/CohereReRanker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACH,YAAY,IAAI,cAAc,EAG9B,WAAW,GACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGvD;;;;;GAKG;AACH,IAAI,uBAAuB,GAAsE,IAAI,CAAC;AAWtG,KAAK,UAAU,mBAAmB;IAC9B,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC3B,uBAAuB,GAAG,CAAC,KAAK,IAAI,EAAE;YAClC,IAAI,CAAC;gBACD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;gBACtC,OAAO,GAAG,CAAC,YAA4E,CAAC;YAC5F,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CACX,mJAAmJ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACxM,CAAC;YACN,CAAC;QACL,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;IACD,OAAO,uBAAuB,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,qBAAsB,SAAQ,cAAc;IAG9C,YAAY,MAAc,EAAE,SAAiB;QACzC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,mBAAmB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/F,CAAC;IAES,KAAK,CAAC,QAAQ,CAAC,MAAoB;QACzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC;QACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,UAAU;YACtB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5C,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM;YAC5C,eAAe,EAAE,KAAK;SACzB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACrC,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;YAChC,cAAc,EAAE,CAAC,CAAC,cAAc;YAChC,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;YACnC,IAAI,EAAE,GAAG;SACZ,CAAC,CAAC,CAAC;IACR,CAAC;CACJ;AAED;;;;;;GAMG;AAEI,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,YAAY;IAC5C,IAAW,WAAW;QAClB,OAAO,gBAAgB,CAAC;IAC5B,CAAC;IACD,IAAoB,IAAI;QACpB,OAAO,QAAQ,CAAC;IACpB,CAAC;IACD,IAAoB,OAAO;QACvB,OAAO,GAAG,CAAC;IACf,CAAC;IAED;;;OAGG;IACa,iBAAiB;QAC7B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACa,iBAAiB,CAAC,WAAmB;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC;QAC3D,OAAO,QAAQ,GAAG,GAAG,CAAC;IAC1B,CAAC;IAEkB,aAAa,CAC5B,MAA2C,EAC3C,YAAsB;QAEtB,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,QAAQ,CAAC,+HAA+H,CAAC,CAAC;YAC1I,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,SAAS,GAAI,MAAM,EAAE,CAAC,OAAO,CAAwB,IAAI,aAAa,CAAC;QAC7E,OAAO,IAAI,qBAAqB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IAED;;;;;OAKG;IACa,KAAK,CAAC,MAAM,CACxB,KAAa,EACb,UAA8B,EAC9B,IAAY,EACZ,WAAqB,EACrB,MAAgC;QAEhC,IAAI,IAAI,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QAChF,wEAAwE;QACxE,8EAA8E;QAC9E,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ,CAAA;AAhEY,cAAc;IAD1B,aAAa,CAAC,YAAY,EAAE,gBAAgB,CAAC;GACjC,cAAc,CAgE1B;;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAC9B,6DAA6D;IAC7D,MAAM,IAAI,GAAG,cAAc,CAAC;AAChC,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @fileoverview OpenAI chat-judge re-ranker (P2D.4).
3
+ *
4
+ * **Decision (2026-04-28):** OpenAI does not publish a first-party reranker endpoint.
5
+ * Their offerings are completions, chat, embeddings, and moderation — there is no
6
+ * dedicated `/rerank`. This implementation uses the documented fallback from the plan:
7
+ * a small chat-completion-based "judge" that scores each candidate's relevance to the
8
+ * query and returns the new ordering. Re-evaluate this decision when OpenAI ships a
9
+ * first-party reranker — the canonical plan calls out swapping in the first-party
10
+ * endpoint as soon as it exists.
11
+ *
12
+ * **Approach.** Single chat completion call, JSON-mode response. The model receives
13
+ * the query and a numbered list of documents and returns
14
+ * `{ "scores": [<number 0..1>, ...] }` with one score per document, in input order.
15
+ * We then sort by score, slice to topN, and return.
16
+ *
17
+ * **Cost.** `gpt-4o-mini` defaults: $0.15 / 1M input tokens, $0.60 / 1M output tokens
18
+ * (2026-04 pricing). Pre-call estimate uses a conservative ~80 tokens/doc input plus
19
+ * 8 tokens/doc output. Post-call cost reports the exact `usage.{prompt,completion}_tokens`
20
+ * from OpenAI so the budget guard sees real spend.
21
+ *
22
+ * **API key.** `GetAIAPIKey('OpenAILLM')` —
23
+ * AI_VENDOR_API_KEY__OPENAILLM or any registered AIAPIKeys subclass.
24
+ *
25
+ * @module @memberjunction/search-engine
26
+ */
27
+ import { UserInfo } from '@memberjunction/core';
28
+ import { BaseReranker as AIBaseReranker } from '@memberjunction/ai';
29
+ import { BaseReRanker } from '../generic/BaseReRanker.js';
30
+ import { SearchResultItem } from '../generic/search.types.js';
31
+ /**
32
+ * Chat-completion-based "judge" reranker. Configure per scope via
33
+ * `SearchScope.ScopeConfig.reRanker.driverClass = 'OpenAIReRanker'`.
34
+ *
35
+ * Override the model via `ScopeConfig.reRanker.config.model`
36
+ * (default: `gpt-4o-mini` — change when a first-party OpenAI rerank endpoint launches).
37
+ */
38
+ export declare class OpenAIReRanker extends BaseReRanker {
39
+ /** Pricing in cents-per-token. As of 2026-04. */
40
+ private static readonly PRICING;
41
+ private currentAIReranker;
42
+ get DriverClass(): string;
43
+ get Name(): string;
44
+ get Version(): string;
45
+ /**
46
+ * Effective limit when the candidate list plus prompt fits in the model's input
47
+ * window. With gpt-4o-mini's 128k input context and ~80 tokens/doc, the practical
48
+ * cap is well above 1000. Returning 1000 to match the other rerankers; the
49
+ * SearchEngine will chunk above this when chunking is implemented.
50
+ */
51
+ GetMaxResultCount(): number;
52
+ /**
53
+ * Pre-call cost estimate. ~80 input tokens/doc + 50 system/query tokens, plus
54
+ * 8 output tokens/doc. Conservative — actual usage tends to be lower.
55
+ */
56
+ EstimateCostCents(resultCount: number): number;
57
+ protected getAIReranker(config: Record<string, unknown> | undefined, _contextUser: UserInfo): AIBaseReranker | null;
58
+ ReRank(query: string, candidates: SearchResultItem[], topN: number, contextUser: UserInfo, config?: Record<string, unknown>): Promise<SearchResultItem[]>;
59
+ }
60
+ /** Tree-shake prevention helper. */
61
+ export declare function LoadOpenAIReRanker(): void;
62
+ //# sourceMappingURL=OpenAIReRanker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenAIReRanker.d.ts","sourceRoot":"","sources":["../../src/rerankers/OpenAIReRanker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACH,YAAY,IAAI,cAAc,EAIjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AA0F3D;;;;;;GAMG;AACH,qBACa,cAAe,SAAQ,YAAY;IAC5C,iDAAiD;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAK7B;IAEF,OAAO,CAAC,iBAAiB,CAAsC;IAE/D,IAAW,WAAW,IAAI,MAAM,CAE/B;IACD,IAAoB,IAAI,IAAI,MAAM,CAEjC;IACD,IAAoB,OAAO,IAAI,MAAM,CAEpC;IAED;;;;;OAKG;IACa,iBAAiB,IAAI,MAAM;IAI3C;;;OAGG;IACa,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;cAO3C,aAAa,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,YAAY,EAAE,QAAQ,GACvB,cAAc,GAAG,IAAI;IAaF,MAAM,CACxB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,gBAAgB,EAAE,EAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,QAAQ,EACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAiBjC;AAED,oCAAoC;AACpC,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC"}