@massa-ai/core 1.14.0 → 1.16.0
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/services/search/contextual-search-rlm.d.ts +35 -14
- package/dist/services/search/contextual-search-rlm.d.ts.map +1 -1
- package/dist/services/search/contextual-search-rlm.js +274 -53
- package/dist/services/search/contextual-search-rlm.js.map +1 -1
- package/dist/services/search/graph-stream.d.ts +36 -0
- package/dist/services/search/graph-stream.d.ts.map +1 -0
- package/dist/services/search/{rlm-synapse.js → graph-stream.js} +11 -90
- package/dist/services/search/graph-stream.js.map +1 -0
- package/dist/services/search/hybrid-search.d.ts +101 -0
- package/dist/services/search/hybrid-search.d.ts.map +1 -0
- package/dist/services/search/{rlm-search.js → hybrid-search.js} +89 -46
- package/dist/services/search/hybrid-search.js.map +1 -0
- package/dist/services/search/index-admin.d.ts +130 -0
- package/dist/services/search/index-admin.d.ts.map +1 -0
- package/dist/services/search/{rlm-admin.js → index-admin.js} +34 -18
- package/dist/services/search/index-admin.js.map +1 -0
- package/dist/services/search/project-indexer.d.ts +159 -0
- package/dist/services/search/project-indexer.d.ts.map +1 -0
- package/dist/services/search/{rlm-indexing.js → project-indexer.js} +51 -79
- package/dist/services/search/project-indexer.js.map +1 -0
- package/dist/services/search/session-bias.d.ts +41 -0
- package/dist/services/search/session-bias.d.ts.map +1 -0
- package/dist/services/search/session-bias.js +76 -0
- package/dist/services/search/session-bias.js.map +1 -0
- package/package.json +2 -2
- package/dist/services/search/rlm-admin.d.ts +0 -22
- package/dist/services/search/rlm-admin.d.ts.map +0 -1
- package/dist/services/search/rlm-admin.js.map +0 -1
- package/dist/services/search/rlm-indexing.d.ts +0 -71
- package/dist/services/search/rlm-indexing.d.ts.map +0 -1
- package/dist/services/search/rlm-indexing.js.map +0 -1
- package/dist/services/search/rlm-search.d.ts +0 -27
- package/dist/services/search/rlm-search.d.ts.map +0 -1
- package/dist/services/search/rlm-search.js.map +0 -1
- package/dist/services/search/rlm-synapse.d.ts +0 -44
- package/dist/services/search/rlm-synapse.d.ts.map +0 -1
- package/dist/services/search/rlm-synapse.js.map +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph-stream — the graph-neighbor RRF stream.
|
|
3
|
+
*
|
|
4
|
+
* PR-B capability module (design.md §4.1). Takes no dependency record at all:
|
|
5
|
+
* it never read a single facade member. Its previous signature accepted the
|
|
6
|
+
* facade as a deliberately-unused `_rlm` purely to match M14's delegate shape,
|
|
7
|
+
* and dropping that parameter is what makes this an extraction rather than a
|
|
8
|
+
* rename — the file has never heard of ContextualSearchRLM, so it contributes
|
|
9
|
+
* nothing to the root's foreign reach (G-HUB, design.md §3.4).
|
|
10
|
+
*
|
|
11
|
+
* Behavior is byte-preserved from rlm-synapse.ts: the body moved verbatim.
|
|
12
|
+
*/
|
|
13
|
+
import { SearchResult } from "@massa-ai/shared";
|
|
14
|
+
import type { SearchDegradationReporter } from "./search-diagnostics.js";
|
|
15
|
+
/**
|
|
16
|
+
* Phase 7c: build the graph-neighbor RRF stream. BFS depth-2 over outgoing
|
|
17
|
+
* memory-graph edges; resolved to SearchResults via the memory repository at
|
|
18
|
+
* a fixed sub-hit score (0.45).
|
|
19
|
+
*
|
|
20
|
+
* Id-bridge fix (A3): graph edges connect MEMORY ids, but vector/code-search
|
|
21
|
+
* results key on chunk ids (e.g. "projectId:path:0"). Seeding BFS with chunk
|
|
22
|
+
* ids therefore silently omitted the stream for code queries — the primary
|
|
23
|
+
* use case. We now bridge the two id spaces: collect graph seeds by (a)
|
|
24
|
+
* trying the raw hit ids (preserves the original behavior for memory search
|
|
25
|
+
* where memory ids already flow in), AND (b) mapping each code chunk to
|
|
26
|
+
* memory ids that reference the same filePath/symbol via fullTextSearch.
|
|
27
|
+
* This makes the graph stream participate for code queries while remaining
|
|
28
|
+
* a silent-omit no-op when no bridged seeds resolve.
|
|
29
|
+
*
|
|
30
|
+
* Degradation (silent-omit): returns [] when the neighbor set is empty, the
|
|
31
|
+
* graph store throws, or the memory repo returns nothing. The caller only
|
|
32
|
+
* appends the stream when non-empty, so `resultSets.length` (and thus the
|
|
33
|
+
* `search:reranked` streamCount) always reflects the real stream count.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildGraphStream(resultSets: SearchResult[][], maxResults: number, projectId?: string, reportDegradation?: SearchDegradationReporter): Promise<SearchResult[]>;
|
|
36
|
+
//# sourceMappingURL=graph-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-stream.d.ts","sourceRoot":"","sources":["../../../src/services/search/graph-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAU,MAAM,kBAAkB,CAAC;AAGxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,YAAY,EAAE,EAAE,EAC5B,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,iBAAiB,CAAC,EAAE,yBAAyB,GAC5C,OAAO,CAAC,YAAY,EAAE,CAAC,CAqHzB"}
|
|
@@ -1,97 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* graph-stream — the graph-neighbor RRF stream.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* PR-B capability module (design.md §4.1). Takes no dependency record at all:
|
|
5
|
+
* it never read a single facade member. Its previous signature accepted the
|
|
6
|
+
* facade as a deliberately-unused `_rlm` purely to match M14's delegate shape,
|
|
7
|
+
* and dropping that parameter is what makes this an extraction rather than a
|
|
8
|
+
* rename — the file has never heard of ContextualSearchRLM, so it contributes
|
|
9
|
+
* nothing to the root's foreign reach (G-HUB, design.md §3.4).
|
|
10
|
+
*
|
|
11
|
+
* Behavior is byte-preserved from rlm-synapse.ts: the body moved verbatim.
|
|
6
12
|
*/
|
|
7
13
|
import { logger } from "@massa-ai/shared";
|
|
8
14
|
import { getMemoryRepository } from "../../data/memory/memory-repository-factory.js";
|
|
9
15
|
import { getGraphStore } from "../graph/graph-store-factory.js";
|
|
10
|
-
import { getSessionRegistry } from "../synapse/session/index.js";
|
|
11
|
-
import { getSynapseManager } from "../synapse/index.js";
|
|
12
|
-
import { extractQueryTerms } from "./lexical-search.js";
|
|
13
|
-
/**
|
|
14
|
-
* Apply session state after the session-independent base result is cached.
|
|
15
|
-
* Invalid and workspace-mismatched sessions return the exact base array.
|
|
16
|
-
*/
|
|
17
|
-
export async function applySynapseStateImpl(rlm, baseResults, query, projectId, sessionId, reportDegradation) {
|
|
18
|
-
if (!sessionId)
|
|
19
|
-
return baseResults;
|
|
20
|
-
const registry = rlm.injectedDeps?.sessionRegistry ?? getSessionRegistry();
|
|
21
|
-
let session;
|
|
22
|
-
try {
|
|
23
|
-
session = await registry.getAsync(sessionId);
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
reportDegradation?.("SYNAPSE_UNAVAILABLE", "synapse_session_lookup");
|
|
27
|
-
logger.warn("Synapse session lookup failed — using stateless search", {
|
|
28
|
-
sessionId,
|
|
29
|
-
projectId,
|
|
30
|
-
error: error.message,
|
|
31
|
-
});
|
|
32
|
-
return baseResults;
|
|
33
|
-
}
|
|
34
|
-
if (!session || (session.workspaceId && session.workspaceId !== projectId)) {
|
|
35
|
-
return baseResults;
|
|
36
|
-
}
|
|
37
|
-
const synapseManager = rlm.injectedDeps?.synapseManager ?? getSynapseManager();
|
|
38
|
-
const allowBufferInjection = session.workspaceId === projectId;
|
|
39
|
-
let processed;
|
|
40
|
-
try {
|
|
41
|
-
processed = synapseManager.process(baseResults, query, {
|
|
42
|
-
session,
|
|
43
|
-
projectId,
|
|
44
|
-
allowBufferInjection,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
reportDegradation?.("SYNAPSE_UNAVAILABLE", "synapse_processing");
|
|
49
|
-
logger.warn("Synapse processing failed — using stateless search", {
|
|
50
|
-
sessionId,
|
|
51
|
-
projectId,
|
|
52
|
-
error: error.message,
|
|
53
|
-
});
|
|
54
|
-
return baseResults;
|
|
55
|
-
}
|
|
56
|
-
const baseIds = new Set(baseResults.map((result) => result.id));
|
|
57
|
-
return processed.results.filter((result) => {
|
|
58
|
-
if (baseIds.has(result.id))
|
|
59
|
-
return true;
|
|
60
|
-
const metadata = result.metadata;
|
|
61
|
-
return allowBufferInjection && metadata?.projectId === projectId;
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Fuzzy-correct each non-stopword query term via the keyword store's
|
|
66
|
-
* vocabulary. Returns the corrected query string (lowercased, space-joined),
|
|
67
|
-
* or null when no term corrects to a different word or fuzzyCorrect is
|
|
68
|
-
* unavailable. Only words of length >= 3 are considered (shorter tokens
|
|
69
|
-
* can't be reliably corrected).
|
|
70
|
-
*/
|
|
71
|
-
export async function correctQueryImpl(rlm, query) {
|
|
72
|
-
if (typeof rlm.keywordSearch.fuzzyCorrect !== "function")
|
|
73
|
-
return null;
|
|
74
|
-
const terms = extractQueryTerms(query).filter((w) => w.length >= 3);
|
|
75
|
-
// Vocabulary-nearest correction is reliable for identifier typo probes
|
|
76
|
-
// ("useEffct") but unsafe for natural-language sentences: ordinary
|
|
77
|
-
// Portuguese words were rewritten to unrelated English code tokens and
|
|
78
|
-
// added as an entire extra RRF stream.
|
|
79
|
-
if (terms.length !== 1)
|
|
80
|
-
return null;
|
|
81
|
-
const corrected = [];
|
|
82
|
-
let changed = false;
|
|
83
|
-
for (const term of terms) {
|
|
84
|
-
const fix = await rlm.keywordSearch.fuzzyCorrect(term);
|
|
85
|
-
if (fix && fix !== term) {
|
|
86
|
-
corrected.push(fix);
|
|
87
|
-
changed = true;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
corrected.push(term);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return changed ? corrected.join(" ") : null;
|
|
94
|
-
}
|
|
95
16
|
/**
|
|
96
17
|
* Phase 7c: build the graph-neighbor RRF stream. BFS depth-2 over outgoing
|
|
97
18
|
* memory-graph edges; resolved to SearchResults via the memory repository at
|
|
@@ -112,7 +33,7 @@ export async function correctQueryImpl(rlm, query) {
|
|
|
112
33
|
* appends the stream when non-empty, so `resultSets.length` (and thus the
|
|
113
34
|
* `search:reranked` streamCount) always reflects the real stream count.
|
|
114
35
|
*/
|
|
115
|
-
export async function
|
|
36
|
+
export async function buildGraphStream(resultSets, maxResults, projectId, reportDegradation) {
|
|
116
37
|
try {
|
|
117
38
|
// Seed candidates = top-N ids + derived filePath/symbol anchors from the
|
|
118
39
|
// first (vector) stream's chunk metadata.
|
|
@@ -234,4 +155,4 @@ export async function buildGraphStreamImpl(_rlm, resultSets, maxResults, project
|
|
|
234
155
|
return [];
|
|
235
156
|
}
|
|
236
157
|
}
|
|
237
|
-
//# sourceMappingURL=
|
|
158
|
+
//# sourceMappingURL=graph-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-stream.js","sourceRoot":"","sources":["../../../src/services/search/graph-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hybrid-search — the hybrid retrieval capability (design.md §4.1).
|
|
3
|
+
*
|
|
4
|
+
* PR-B capability module, completed at T13. T9 created it with `correctQuery`
|
|
5
|
+
* alone; T13 moved `search`, `addContextToResults`, `extractPreview`,
|
|
6
|
+
* `calculateAvgScore` and `filterByPatterns` here, and `rlm-search.ts` dies whole
|
|
7
|
+
* in that commit — the fourth `rlm-*.ts` source to do so, and the last. This file
|
|
8
|
+
* has never heard of ContextualSearchRLM, which is what takes the root's foreign
|
|
9
|
+
* reach 14 → 1 and closes G-HUB (§3.4). `correctQuery` arrived from
|
|
10
|
+
* rlm-synapse.ts, not rlm-search.ts: it reads `keywordSearch`, the collaborator
|
|
11
|
+
* this module already owns, and its only caller is `search` (§4.2).
|
|
12
|
+
* `extractQueryTerms` / `applyProximityRerank` are *imported* from
|
|
13
|
+
* lexical-search.ts, never moved: that module carries a `data/` importer and is
|
|
14
|
+
* PR-C's to place (§5.4, PR-C-BOUNDARY). Behavior is byte-preserved from both
|
|
15
|
+
* sources — bodies verbatim, `rlm.<member>` rewritten per the disposition on
|
|
16
|
+
* `HybridSearchDeps` below and in full in tasks.md.
|
|
17
|
+
*/
|
|
18
|
+
import { SearchResult } from "@massa-ai/shared";
|
|
19
|
+
import type { QueryUnderstandingService } from "./query-understanding.js";
|
|
20
|
+
import type { getKeywordSearch } from "../../data/keyword/keyword-search-factory.js";
|
|
21
|
+
import type { getVectorStore } from "../../data/vector/vector-store-factory.js";
|
|
22
|
+
import type { getSearchCache } from "./cache-factory.js";
|
|
23
|
+
import type { getSearchAnalytics } from "./analytics-factory.js";
|
|
24
|
+
import { type SearchDegradation, type SearchDegradationReporter } from "./search-diagnostics.js";
|
|
25
|
+
/**
|
|
26
|
+
* The narrow dependency record for this module (design.md §4.4) — exactly the
|
|
27
|
+
* collaborators §2.1 shows these surfaces read, and nothing else. §2.1 records
|
|
28
|
+
* `searchImpl` reading **13** facade members, the highest arity in the matrix;
|
|
29
|
+
* each one's disposition was decided by measuring the instance-stub sites that
|
|
30
|
+
* reach it, not by reading §4.1's "injected collaborators" column, which names
|
|
31
|
+
* five and is a store list rather than a member list. **The disposition table,
|
|
32
|
+
* the stub-site counts, the sweep method and the two-variant `queryUnderstanding`
|
|
33
|
+
* simulation are in tasks.md, "T13 — the disposition of §2.1's thirteen".**
|
|
34
|
+
*
|
|
35
|
+
* Four invariants this file must keep, each with a measurement behind it there:
|
|
36
|
+
*
|
|
37
|
+
* 1. `queryUnderstanding` stays `Pick<>`-narrowed — honest typing per §4.4, and
|
|
38
|
+
* **not** a fired sensor: bare nominal reaches 1, under the ceiling of 3.
|
|
39
|
+
* 2. The three callbacks stay **per-call arrow wrappers** — never `.bind(this)`,
|
|
40
|
+
* never bare method references, both of which resolve at *assembly* time.
|
|
41
|
+
* `buildGraphStream` and `addContextToResults` are each stubbed on the
|
|
42
|
+
* instance at 6 sites; a module-local call disables all twelve silently.
|
|
43
|
+
* 3. `ensureInitialized` is **not** a member of this record, and `search` must
|
|
44
|
+
* not call it. The root hoists it — carrying the `searchBackendUnavailable`
|
|
45
|
+
* wrap `searchImpl` used to apply — because the five stores below are
|
|
46
|
+
* snapshotted **by value**, so a record assembled before init holds five
|
|
47
|
+
* `undefined`s. Measured: rlm-search 31 → 15/16 the other way round.
|
|
48
|
+
* 4. The five stores stay required and keep the root's own field types — their
|
|
49
|
+
* originals were bare reads off definite-assigned fields with no fallback, so
|
|
50
|
+
* an absent store must keep throwing exactly where it did.
|
|
51
|
+
*
|
|
52
|
+
* `hybrid-search-late-bind.test.ts` test 4 is the compensating control for
|
|
53
|
+
* invariant 2, and what makes the coverage file's three `expect.any(Function)`
|
|
54
|
+
* keys acceptable rather than a relaxation. `correctQuery` takes this whole
|
|
55
|
+
* record while reading one field of it — the `getAnalytics`/`IndexAdminDeps`
|
|
56
|
+
* shape from T12; §4.4's narrowness is a property of the *module*'s record, not
|
|
57
|
+
* of each surface's parameter list.
|
|
58
|
+
*/
|
|
59
|
+
export interface HybridSearchDeps {
|
|
60
|
+
keywordSearch: Awaited<ReturnType<typeof getKeywordSearch>>;
|
|
61
|
+
vectorStore: Awaited<ReturnType<typeof getVectorStore>>;
|
|
62
|
+
searchCache: Awaited<ReturnType<typeof getSearchCache>>;
|
|
63
|
+
analytics: Awaited<ReturnType<typeof getSearchAnalytics>>;
|
|
64
|
+
queryUnderstanding: Pick<QueryUnderstandingService, "understand">;
|
|
65
|
+
buildGraphStream: (resultSets: SearchResult[][], maxResults: number, projectId?: string, reportDegradation?: SearchDegradationReporter) => Promise<SearchResult[]>;
|
|
66
|
+
addContextToResults: (results: SearchResult[], projectId: string) => Promise<SearchResult[]>;
|
|
67
|
+
applySynapseState: (baseResults: SearchResult[], query: string, projectId: string, sessionId?: string, reportDegradation?: SearchDegradationReporter) => Promise<SearchResult[]>;
|
|
68
|
+
}
|
|
69
|
+
export type SearchOptions = {
|
|
70
|
+
maxResults?: number;
|
|
71
|
+
minScore?: number;
|
|
72
|
+
explainScores?: boolean;
|
|
73
|
+
includeFilters?: string[];
|
|
74
|
+
excludeFilters?: string[];
|
|
75
|
+
/** Phase 2: Synapse session id forwarded for future Synapse-biased fusion. */
|
|
76
|
+
sessionId?: string;
|
|
77
|
+
/** Receives bounded, sanitized evidence for optional search failures. */
|
|
78
|
+
onDegradations?: (degradations: readonly SearchDegradation[]) => void;
|
|
79
|
+
};
|
|
80
|
+
export declare function search(deps: HybridSearchDeps, query: string, projectId: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Fuzzy-correct each non-stopword query term via the keyword store's
|
|
83
|
+
* vocabulary. Returns the corrected query string (lowercased, space-joined),
|
|
84
|
+
* or null when no term corrects to a different word or fuzzyCorrect is
|
|
85
|
+
* unavailable. Only words of length >= 3 are considered (shorter tokens
|
|
86
|
+
* can't be reliably corrected).
|
|
87
|
+
*/
|
|
88
|
+
export declare function correctQuery(deps: HybridSearchDeps, query: string): Promise<string | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Takes **no deps record** (§4.4): §2.1 shows its only facade read was
|
|
91
|
+
* `extractPreview`, which now lives beside it here, so the honest parameter list
|
|
92
|
+
* is the data alone — the shape `fuseResults` and `buildGraphStream` already
|
|
93
|
+
* have. GMS-03 AC-1 is satisfied by the absent facade argument, not by a record.
|
|
94
|
+
* `search` still reaches it through `deps.addContextToResults` rather than
|
|
95
|
+
* calling it module-locally — see the 6 stub sites noted above.
|
|
96
|
+
*/
|
|
97
|
+
export declare function addContextToResults(results: SearchResult[], _projectId: string): Promise<SearchResult[]>;
|
|
98
|
+
export declare function extractPreview(content: string, maxLines?: number): string;
|
|
99
|
+
export declare function calculateAvgScore(results: SearchResult[]): number;
|
|
100
|
+
export declare function filterByPatterns(results: SearchResult[], include?: string[], exclude?: string[]): SearchResult[];
|
|
101
|
+
//# sourceMappingURL=hybrid-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-search.d.ts","sourceRoot":"","sources":["../../../src/services/search/hybrid-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* for ContextualSearchRLM.
|
|
2
|
+
* hybrid-search — the hybrid retrieval capability (design.md §4.1).
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* PR-B capability module, completed at T13. T9 created it with `correctQuery`
|
|
5
|
+
* alone; T13 moved `search`, `addContextToResults`, `extractPreview`,
|
|
6
|
+
* `calculateAvgScore` and `filterByPatterns` here, and `rlm-search.ts` dies whole
|
|
7
|
+
* in that commit — the fourth `rlm-*.ts` source to do so, and the last. This file
|
|
8
|
+
* has never heard of ContextualSearchRLM, which is what takes the root's foreign
|
|
9
|
+
* reach 14 → 1 and closes G-HUB (§3.4). `correctQuery` arrived from
|
|
10
|
+
* rlm-synapse.ts, not rlm-search.ts: it reads `keywordSearch`, the collaborator
|
|
11
|
+
* this module already owns, and its only caller is `search` (§4.2).
|
|
12
|
+
* `extractQueryTerms` / `applyProximityRerank` are *imported* from
|
|
13
|
+
* lexical-search.ts, never moved: that module carries a `data/` importer and is
|
|
14
|
+
* PR-C's to place (§5.4, PR-C-BOUNDARY). Behavior is byte-preserved from both
|
|
15
|
+
* sources — bodies verbatim, `rlm.<member>` rewritten per the disposition on
|
|
16
|
+
* `HybridSearchDeps` below and in full in tasks.md.
|
|
7
17
|
*/
|
|
8
18
|
import { logger, config } from "@massa-ai/shared";
|
|
9
19
|
import { minimatch } from "minimatch";
|
|
10
20
|
import { buildRewrittenFTSQuery } from "./query-understanding.js";
|
|
11
|
-
import { applyProximityRerank } from "./lexical-search.js";
|
|
21
|
+
import { applyProximityRerank, extractQueryTerms } from "./lexical-search.js";
|
|
12
22
|
import { eventBus } from "../events/event-bus.js";
|
|
23
|
+
import { fuseResults } from "./result-fusion.js";
|
|
13
24
|
import { recordSearchDegradation, recordSearchFailure, searchBackendUnavailable, SearchServiceError, storeCorruption, } from "./search-diagnostics.js";
|
|
14
|
-
export async function
|
|
15
|
-
try {
|
|
16
|
-
await rlm.ensureInitialized();
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
const failure = searchBackendUnavailable("search_initialization", error);
|
|
20
|
-
recordSearchFailure(failure, projectId);
|
|
21
|
-
throw failure;
|
|
22
|
-
}
|
|
25
|
+
export async function search(deps, query, projectId, options = {}) {
|
|
23
26
|
const maxResults = options.maxResults ?? 10;
|
|
24
27
|
const minScore = options.minScore ?? 0.3;
|
|
25
28
|
const explainScores = options.explainScores || false;
|
|
@@ -82,7 +85,7 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
82
85
|
};
|
|
83
86
|
let cachedResults;
|
|
84
87
|
try {
|
|
85
|
-
cachedResults = await
|
|
88
|
+
cachedResults = await deps.searchCache.get(query, projectId, cacheOptions);
|
|
86
89
|
}
|
|
87
90
|
catch (error) {
|
|
88
91
|
const failure = searchBackendUnavailable("search_cache_read", error);
|
|
@@ -102,14 +105,14 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
102
105
|
});
|
|
103
106
|
// Track cache hit
|
|
104
107
|
try {
|
|
105
|
-
|
|
108
|
+
deps.analytics.trackSearch({
|
|
106
109
|
timestamp: Date.now(),
|
|
107
110
|
projectId,
|
|
108
111
|
query,
|
|
109
112
|
resultCount: cachedResults.length,
|
|
110
113
|
duration,
|
|
111
114
|
cacheHit: true,
|
|
112
|
-
score:
|
|
115
|
+
score: calculateAvgScore(cachedResults),
|
|
113
116
|
});
|
|
114
117
|
}
|
|
115
118
|
catch {
|
|
@@ -123,7 +126,7 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
123
126
|
preciseMs: `${(endTime - startTime).toFixed(3)}ms`,
|
|
124
127
|
});
|
|
125
128
|
try {
|
|
126
|
-
return await
|
|
129
|
+
return await deps.applySynapseState(cachedResults, query, projectId, options.sessionId, degrade);
|
|
127
130
|
}
|
|
128
131
|
catch {
|
|
129
132
|
degrade("SYNAPSE_UNAVAILABLE", "synapse");
|
|
@@ -139,7 +142,7 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
139
142
|
try {
|
|
140
143
|
const qu = config.get("search").queryUnderstanding;
|
|
141
144
|
if (qu?.enabled && query.trim()) {
|
|
142
|
-
understood = await
|
|
145
|
+
understood = await deps.queryUnderstanding.understand(query, projectId);
|
|
143
146
|
if (!understood) {
|
|
144
147
|
degrade("QUERY_UNDERSTANDING_UNAVAILABLE", "query_understanding");
|
|
145
148
|
}
|
|
@@ -162,16 +165,16 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
162
165
|
degrade("SEARCH_AUDIT_UNAVAILABLE", "search_query_rewritten_event");
|
|
163
166
|
}
|
|
164
167
|
const rewrittenFTS = buildRewrittenFTSQuery(query, understood.keywords);
|
|
165
|
-
const vectorPromise =
|
|
168
|
+
const vectorPromise = deps.vectorStore
|
|
166
169
|
.search(query, retrievalLimit, projectId)
|
|
167
170
|
.catch((error) => { throw searchBackendUnavailable("vector_search", error); });
|
|
168
171
|
const keywordPromise = disableKeyword
|
|
169
172
|
? Promise.resolve([])
|
|
170
|
-
:
|
|
173
|
+
: deps.keywordSearch
|
|
171
174
|
.searchWithFilter(rewrittenFTS, { projectId }, retrievalLimit)
|
|
172
175
|
.catch((error) => { throw searchBackendUnavailable("keyword_search", error); });
|
|
173
176
|
const hydePromise = understood.hydeVector
|
|
174
|
-
?
|
|
177
|
+
? deps.vectorStore
|
|
175
178
|
.searchByEmbedding(understood.hydeVector, retrievalLimit, projectId)
|
|
176
179
|
.catch(() => {
|
|
177
180
|
degrade("QUERY_UNDERSTANDING_UNAVAILABLE", "hyde_search");
|
|
@@ -195,18 +198,18 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
195
198
|
// streams fuse via RRF; empty streams contribute nothing.
|
|
196
199
|
const fetchN = retrievalLimit;
|
|
197
200
|
const [vectorResults, keywordResults, trigramResults] = await Promise.all([
|
|
198
|
-
|
|
201
|
+
deps.vectorStore
|
|
199
202
|
.search(query, fetchN, projectId)
|
|
200
203
|
.catch((error) => { throw searchBackendUnavailable("vector_search", error); }),
|
|
201
204
|
disableKeyword
|
|
202
205
|
? Promise.resolve([])
|
|
203
|
-
:
|
|
206
|
+
: deps.keywordSearch
|
|
204
207
|
.searchWithFilter(query, { projectId }, fetchN)
|
|
205
208
|
.catch((error) => { throw searchBackendUnavailable("keyword_search", error); }),
|
|
206
209
|
// Trigram stream (best-effort; [] when tokenizer unavailable).
|
|
207
|
-
disableKeyword || !
|
|
210
|
+
disableKeyword || !deps.keywordSearch.searchTrigram
|
|
208
211
|
? Promise.resolve([])
|
|
209
|
-
:
|
|
212
|
+
: deps.keywordSearch
|
|
210
213
|
.searchTrigram(query, { projectId }, fetchN)
|
|
211
214
|
.catch(() => {
|
|
212
215
|
degrade("TRIGRAM_UNAVAILABLE", "trigram_search");
|
|
@@ -224,10 +227,10 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
224
227
|
// add both as RRF streams. This recovers typos like "useEffct" →
|
|
225
228
|
// "useEffect" that porter/trigram miss. Best-effort; skipped when no
|
|
226
229
|
// correction applies or fuzzyCorrect is unavailable.
|
|
227
|
-
if (!disableKeyword && typeof
|
|
230
|
+
if (!disableKeyword && typeof deps.keywordSearch.fuzzyCorrect === "function") {
|
|
228
231
|
let corrected = null;
|
|
229
232
|
try {
|
|
230
|
-
corrected = await
|
|
233
|
+
corrected = await correctQuery(deps, query);
|
|
231
234
|
}
|
|
232
235
|
catch {
|
|
233
236
|
degrade("FUZZY_SEARCH_UNAVAILABLE", "fuzzy_correction");
|
|
@@ -235,14 +238,14 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
235
238
|
if (corrected && corrected !== query.toLowerCase().trim()) {
|
|
236
239
|
try {
|
|
237
240
|
const [fuzzyKeyword, fuzzyTrigram] = await Promise.all([
|
|
238
|
-
|
|
241
|
+
deps.keywordSearch
|
|
239
242
|
.searchWithFilter(corrected, { projectId }, fetchN)
|
|
240
243
|
.catch(() => {
|
|
241
244
|
degrade("FUZZY_SEARCH_UNAVAILABLE", "fuzzy_keyword_search");
|
|
242
245
|
return [];
|
|
243
246
|
}),
|
|
244
|
-
|
|
245
|
-
?
|
|
247
|
+
deps.keywordSearch.searchTrigram
|
|
248
|
+
? deps.keywordSearch
|
|
246
249
|
.searchTrigram(corrected, { projectId }, fetchN)
|
|
247
250
|
.catch(() => {
|
|
248
251
|
degrade("FUZZY_SEARCH_UNAVAILABLE", "fuzzy_trigram_search");
|
|
@@ -274,7 +277,7 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
274
277
|
// the actual stream count). No graph-stream throw escapes this optional path.
|
|
275
278
|
let graphStream = [];
|
|
276
279
|
try {
|
|
277
|
-
graphStream = await
|
|
280
|
+
graphStream = await deps.buildGraphStream(resultSets, maxResults, projectId, degrade);
|
|
278
281
|
}
|
|
279
282
|
catch {
|
|
280
283
|
degrade("GRAPH_AUGMENTATION_UNAVAILABLE", "graph_augmentation");
|
|
@@ -283,7 +286,7 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
283
286
|
resultSets = [...resultSets, graphStream];
|
|
284
287
|
}
|
|
285
288
|
// Combine results using RRF (with score explanation if requested)
|
|
286
|
-
const fusedResults =
|
|
289
|
+
const fusedResults = fuseResults(resultSets, query, explainScores);
|
|
287
290
|
// A2: proximity + title re-ranking pass (post-RRF, pre-filter). Stable
|
|
288
291
|
// re-rank on top of RRF: boosts results whose title contains query terms
|
|
289
292
|
// and whose body positions the terms close together; code chunks get a
|
|
@@ -321,7 +324,7 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
321
324
|
let filteredByPattern = fusedReranked;
|
|
322
325
|
if (includeFilters || excludeFilters) {
|
|
323
326
|
const filterStartTime = performance.now();
|
|
324
|
-
filteredByPattern =
|
|
327
|
+
filteredByPattern = filterByPatterns(fusedReranked, includeFilters, excludeFilters);
|
|
325
328
|
const filterDuration = performance.now() - filterStartTime;
|
|
326
329
|
logger.debug("Applied file pattern filters", {
|
|
327
330
|
beforeFilter: fusedReranked.length,
|
|
@@ -367,14 +370,14 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
367
370
|
// Add context to results
|
|
368
371
|
let withContext;
|
|
369
372
|
try {
|
|
370
|
-
withContext = await
|
|
373
|
+
withContext = await deps.addContextToResults(filtered, projectId);
|
|
371
374
|
}
|
|
372
375
|
catch (error) {
|
|
373
376
|
throw storeCorruption("search_result_hydration", error);
|
|
374
377
|
}
|
|
375
378
|
// Cache the results
|
|
376
379
|
try {
|
|
377
|
-
await
|
|
380
|
+
await deps.searchCache.set(query, projectId, withContext, cacheOptions);
|
|
378
381
|
}
|
|
379
382
|
catch (error) {
|
|
380
383
|
throw searchBackendUnavailable("search_cache_write", error);
|
|
@@ -382,14 +385,14 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
382
385
|
const duration = Math.round(performance.now() - startTime); // Use performance.now() for consistency
|
|
383
386
|
// Track cache miss
|
|
384
387
|
try {
|
|
385
|
-
|
|
388
|
+
deps.analytics.trackSearch({
|
|
386
389
|
timestamp: Date.now(),
|
|
387
390
|
projectId,
|
|
388
391
|
query,
|
|
389
392
|
resultCount: withContext.length,
|
|
390
393
|
duration,
|
|
391
394
|
cacheHit: false,
|
|
392
|
-
score:
|
|
395
|
+
score: calculateAvgScore(withContext),
|
|
393
396
|
});
|
|
394
397
|
}
|
|
395
398
|
catch {
|
|
@@ -398,11 +401,11 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
398
401
|
logger.info("Contextual search completed", {
|
|
399
402
|
projectId,
|
|
400
403
|
totalResults: withContext.length,
|
|
401
|
-
avgScore:
|
|
404
|
+
avgScore: calculateAvgScore(withContext),
|
|
402
405
|
duration,
|
|
403
406
|
});
|
|
404
407
|
try {
|
|
405
|
-
return await
|
|
408
|
+
return await deps.applySynapseState(withContext, query, projectId, options.sessionId, degrade);
|
|
406
409
|
}
|
|
407
410
|
catch {
|
|
408
411
|
degrade("SYNAPSE_UNAVAILABLE", "synapse");
|
|
@@ -420,8 +423,48 @@ export async function searchImpl(rlm, query, projectId, options = {}) {
|
|
|
420
423
|
throw error;
|
|
421
424
|
}
|
|
422
425
|
}
|
|
426
|
+
// ── correctQuery ─────────────────────────────────────────────────────────────
|
|
427
|
+
/**
|
|
428
|
+
* Fuzzy-correct each non-stopword query term via the keyword store's
|
|
429
|
+
* vocabulary. Returns the corrected query string (lowercased, space-joined),
|
|
430
|
+
* or null when no term corrects to a different word or fuzzyCorrect is
|
|
431
|
+
* unavailable. Only words of length >= 3 are considered (shorter tokens
|
|
432
|
+
* can't be reliably corrected).
|
|
433
|
+
*/
|
|
434
|
+
export async function correctQuery(deps, query) {
|
|
435
|
+
if (typeof deps.keywordSearch.fuzzyCorrect !== "function")
|
|
436
|
+
return null;
|
|
437
|
+
const terms = extractQueryTerms(query).filter((w) => w.length >= 3);
|
|
438
|
+
// Vocabulary-nearest correction is reliable for identifier typo probes
|
|
439
|
+
// ("useEffct") but unsafe for natural-language sentences: ordinary
|
|
440
|
+
// Portuguese words were rewritten to unrelated English code tokens and
|
|
441
|
+
// added as an entire extra RRF stream.
|
|
442
|
+
if (terms.length !== 1)
|
|
443
|
+
return null;
|
|
444
|
+
const corrected = [];
|
|
445
|
+
let changed = false;
|
|
446
|
+
for (const term of terms) {
|
|
447
|
+
const fix = await deps.keywordSearch.fuzzyCorrect(term);
|
|
448
|
+
if (fix && fix !== term) {
|
|
449
|
+
corrected.push(fix);
|
|
450
|
+
changed = true;
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
corrected.push(term);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return changed ? corrected.join(" ") : null;
|
|
457
|
+
}
|
|
423
458
|
// ── addContextToResults ──────────────────────────────────────────────────────
|
|
424
|
-
|
|
459
|
+
/**
|
|
460
|
+
* Takes **no deps record** (§4.4): §2.1 shows its only facade read was
|
|
461
|
+
* `extractPreview`, which now lives beside it here, so the honest parameter list
|
|
462
|
+
* is the data alone — the shape `fuseResults` and `buildGraphStream` already
|
|
463
|
+
* have. GMS-03 AC-1 is satisfied by the absent facade argument, not by a record.
|
|
464
|
+
* `search` still reaches it through `deps.addContextToResults` rather than
|
|
465
|
+
* calling it module-locally — see the 6 stub sites noted above.
|
|
466
|
+
*/
|
|
467
|
+
export async function addContextToResults(results, _projectId) {
|
|
425
468
|
return results.map((result) => {
|
|
426
469
|
const metadata = result.metadata;
|
|
427
470
|
const filePath = metadata?.filePath;
|
|
@@ -437,7 +480,7 @@ export async function addContextToResultsImpl(rlm, results, _projectId) {
|
|
|
437
480
|
filePath,
|
|
438
481
|
lineStart,
|
|
439
482
|
lineEnd,
|
|
440
|
-
preview:
|
|
483
|
+
preview: extractPreview(result.content),
|
|
441
484
|
},
|
|
442
485
|
},
|
|
443
486
|
};
|
|
@@ -446,20 +489,20 @@ export async function addContextToResultsImpl(rlm, results, _projectId) {
|
|
|
446
489
|
});
|
|
447
490
|
}
|
|
448
491
|
// ── extractPreview ───────────────────────────────────────────────────────────
|
|
449
|
-
export function
|
|
492
|
+
export function extractPreview(content, maxLines = 5) {
|
|
450
493
|
const lines = content.split("\n");
|
|
451
494
|
const preview = lines.slice(0, maxLines).join("\n");
|
|
452
495
|
return lines.length > maxLines ? preview + "\n..." : preview;
|
|
453
496
|
}
|
|
454
497
|
// ── calculateAvgScore ────────────────────────────────────────────────────────
|
|
455
|
-
export function
|
|
498
|
+
export function calculateAvgScore(results) {
|
|
456
499
|
if (results.length === 0)
|
|
457
500
|
return 0;
|
|
458
501
|
const sum = results.reduce((acc, r) => acc + r.score, 0);
|
|
459
502
|
return sum / results.length;
|
|
460
503
|
}
|
|
461
504
|
// ── filterByPatterns ─────────────────────────────────────────────────────────
|
|
462
|
-
export function
|
|
505
|
+
export function filterByPatterns(results, include, exclude) {
|
|
463
506
|
if (!include && !exclude) {
|
|
464
507
|
return results;
|
|
465
508
|
}
|
|
@@ -482,4 +525,4 @@ export function filterByPatternsImpl(results, include, exclude) {
|
|
|
482
525
|
return true;
|
|
483
526
|
});
|
|
484
527
|
}
|
|
485
|
-
//# sourceMappingURL=
|
|
528
|
+
//# sourceMappingURL=hybrid-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-search.js","sourceRoot":"","sources":["../../../src/services/search/hybrid-search.ts"],"names":[],"mappings":"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"}
|