@mhalder/qdrant-mcp-server 3.3.3 → 3.3.4
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/.github/workflows/ci.yml +0 -2
- package/.github/workflows/claude-code-review.yml +1 -1
- package/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/biome.json +3 -2
- package/build/code/chunker/tree-sitter-chunker.d.ts.map +1 -1
- package/build/code/chunker/tree-sitter-chunker.js +2 -12
- package/build/code/chunker/tree-sitter-chunker.js.map +1 -1
- package/build/code/indexer.d.ts.map +1 -1
- package/build/code/indexer.js +12 -18
- package/build/code/indexer.js.map +1 -1
- package/build/code/scanner.js +1 -1
- package/build/code/scanner.js.map +1 -1
- package/build/embeddings/cohere.d.ts +1 -1
- package/build/embeddings/cohere.d.ts.map +1 -1
- package/build/embeddings/cohere.js +2 -2
- package/build/embeddings/cohere.js.map +1 -1
- package/build/embeddings/cohere.test.js +1 -5
- package/build/embeddings/cohere.test.js.map +1 -1
- package/build/embeddings/factory.d.ts +1 -1
- package/build/embeddings/factory.d.ts.map +1 -1
- package/build/embeddings/factory.js +7 -9
- package/build/embeddings/factory.js.map +1 -1
- package/build/embeddings/factory.test.js +3 -3
- package/build/embeddings/factory.test.js.map +1 -1
- package/build/embeddings/ollama.d.ts +1 -1
- package/build/embeddings/ollama.d.ts.map +1 -1
- package/build/embeddings/ollama.js +6 -8
- package/build/embeddings/ollama.js.map +1 -1
- package/build/embeddings/ollama.test.js +2 -6
- package/build/embeddings/ollama.test.js.map +1 -1
- package/build/embeddings/openai.d.ts +1 -1
- package/build/embeddings/openai.d.ts.map +1 -1
- package/build/embeddings/openai.js +4 -7
- package/build/embeddings/openai.js.map +1 -1
- package/build/embeddings/openai.test.js +3 -12
- package/build/embeddings/openai.test.js.map +1 -1
- package/build/embeddings/sparse.test.js +12 -2
- package/build/embeddings/sparse.test.js.map +1 -1
- package/build/embeddings/voyage.d.ts +1 -1
- package/build/embeddings/voyage.d.ts.map +1 -1
- package/build/embeddings/voyage.js +2 -3
- package/build/embeddings/voyage.js.map +1 -1
- package/build/embeddings/voyage.test.js +2 -6
- package/build/embeddings/voyage.test.js.map +1 -1
- package/build/git/chunker.d.ts.map +1 -1
- package/build/git/chunker.js +2 -2
- package/build/git/chunker.js.map +1 -1
- package/build/git/chunker.test.js +1 -1
- package/build/git/chunker.test.js.map +1 -1
- package/build/git/extractor.d.ts.map +1 -1
- package/build/git/extractor.integration.test.js +9 -5
- package/build/git/extractor.integration.test.js.map +1 -1
- package/build/git/extractor.js +1 -1
- package/build/git/extractor.js.map +1 -1
- package/build/git/extractor.test.js +2 -2
- package/build/git/extractor.test.js.map +1 -1
- package/build/git/index.d.ts +4 -4
- package/build/git/index.d.ts.map +1 -1
- package/build/git/index.js +3 -3
- package/build/git/index.js.map +1 -1
- package/build/git/indexer.d.ts.map +1 -1
- package/build/git/indexer.js +9 -21
- package/build/git/indexer.js.map +1 -1
- package/build/git/indexer.test.js +4 -8
- package/build/git/indexer.test.js.map +1 -1
- package/build/git/sync/synchronizer.d.ts.map +1 -1
- package/build/git/sync/synchronizer.js.map +1 -1
- package/build/git/sync/synchronizer.test.js +4 -2
- package/build/git/sync/synchronizer.test.js.map +1 -1
- package/build/index.js +5 -9
- package/build/index.js.map +1 -1
- package/build/index.test.js +3 -3
- package/build/index.test.js.map +1 -1
- package/build/logger.d.ts.map +1 -1
- package/build/logger.js +1 -9
- package/build/logger.js.map +1 -1
- package/build/prompts/register.d.ts.map +1 -1
- package/build/prompts/register.js.map +1 -1
- package/build/qdrant/client.d.ts.map +1 -1
- package/build/qdrant/client.js.map +1 -1
- package/build/qdrant/client.test.js +10 -34
- package/build/qdrant/client.test.js.map +1 -1
- package/build/resources/index.d.ts +1 -1
- package/build/resources/index.d.ts.map +1 -1
- package/build/resources/index.js +1 -1
- package/build/resources/index.js.map +1 -1
- package/build/tools/code.d.ts.map +1 -1
- package/build/tools/code.js +3 -9
- package/build/tools/code.js.map +1 -1
- package/build/tools/collection.d.ts.map +1 -1
- package/build/tools/collection.js +1 -3
- package/build/tools/collection.js.map +1 -1
- package/build/tools/document.d.ts.map +1 -1
- package/build/tools/document.js +1 -1
- package/build/tools/document.js.map +1 -1
- package/build/tools/federated.d.ts.map +1 -1
- package/build/tools/federated.js +15 -6
- package/build/tools/federated.js.map +1 -1
- package/build/tools/federated.test.js +18 -22
- package/build/tools/federated.test.js.map +1 -1
- package/build/tools/git-history.d.ts.map +1 -1
- package/build/tools/git-history.js +3 -7
- package/build/tools/git-history.js.map +1 -1
- package/build/tools/index.d.ts.map +1 -1
- package/build/tools/index.js.map +1 -1
- package/build/tools/logging.d.ts.map +1 -1
- package/build/tools/logging.js +1 -3
- package/build/tools/logging.js.map +1 -1
- package/build/tools/logging.test.js +1 -1
- package/build/tools/logging.test.js.map +1 -1
- package/build/tools/schemas.d.ts.map +1 -1
- package/build/tools/schemas.js +17 -64
- package/build/tools/schemas.js.map +1 -1
- package/build/tools/search.d.ts.map +1 -1
- package/build/tools/search.js +1 -1
- package/build/tools/search.js.map +1 -1
- package/commitlint.config.js +12 -23
- package/package.json +1 -1
- package/scripts/verify-providers.js +12 -32
- package/src/code/chunker/tree-sitter-chunker.ts +9 -35
- package/src/code/indexer.ts +45 -107
- package/src/code/scanner.ts +1 -1
- package/src/embeddings/cohere.test.ts +17 -45
- package/src/embeddings/cohere.ts +10 -17
- package/src/embeddings/factory.test.ts +18 -18
- package/src/embeddings/factory.ts +18 -25
- package/src/embeddings/ollama.test.ts +38 -67
- package/src/embeddings/ollama.ts +15 -27
- package/src/embeddings/openai.test.ts +17 -53
- package/src/embeddings/openai.ts +11 -22
- package/src/embeddings/sparse.test.ts +12 -2
- package/src/embeddings/voyage.test.ts +39 -80
- package/src/embeddings/voyage.ts +9 -13
- package/src/git/chunker.test.ts +1 -1
- package/src/git/chunker.ts +6 -22
- package/src/git/extractor.integration.test.ts +12 -16
- package/src/git/extractor.test.ts +21 -35
- package/src/git/extractor.ts +14 -36
- package/src/git/index.ts +9 -10
- package/src/git/indexer.test.ts +29 -57
- package/src/git/indexer.ts +38 -86
- package/src/git/sync/synchronizer.test.ts +6 -9
- package/src/git/sync/synchronizer.ts +2 -5
- package/src/index.test.ts +7 -9
- package/src/index.ts +34 -80
- package/src/logger.ts +3 -14
- package/src/prompts/register.ts +3 -10
- package/src/qdrant/client.test.ts +63 -169
- package/src/qdrant/client.ts +19 -45
- package/src/resources/index.ts +4 -10
- package/src/tools/code.ts +43 -66
- package/src/tools/collection.ts +19 -38
- package/src/tools/document.ts +10 -19
- package/src/tools/federated.test.ts +34 -57
- package/src/tools/federated.ts +88 -108
- package/src/tools/git-history.ts +32 -60
- package/src/tools/index.ts +1 -4
- package/src/tools/logging.test.ts +10 -10
- package/src/tools/logging.ts +8 -18
- package/src/tools/schemas.ts +23 -78
- package/src/tools/search.ts +77 -94
- package/tests/code/chunker/tree-sitter-chunker.test.ts +6 -19
- package/tests/code/indexer.test.ts +100 -192
- package/tests/code/integration.test.ts +61 -117
- package/tests/code/scanner.test.ts +12 -39
- package/tests/code/sync/snapshot.test.ts +4 -14
- package/tests/code/sync/synchronizer.test.ts +10 -40
package/src/tools/schemas.ts
CHANGED
|
@@ -36,58 +36,40 @@ export const AddDocumentsSchema = {
|
|
|
36
36
|
documents: z
|
|
37
37
|
.array(
|
|
38
38
|
z.object({
|
|
39
|
-
id: z
|
|
40
|
-
.union([z.string(), z.number()])
|
|
41
|
-
.describe("Unique identifier for the document"),
|
|
39
|
+
id: z.union([z.string(), z.number()]).describe("Unique identifier for the document"),
|
|
42
40
|
text: z.string().describe("Text content to embed and store"),
|
|
43
41
|
metadata: z
|
|
44
42
|
.record(z.string(), z.any())
|
|
45
43
|
.optional()
|
|
46
44
|
.describe("Optional metadata to store with the document"),
|
|
47
|
-
})
|
|
45
|
+
})
|
|
48
46
|
)
|
|
49
47
|
.describe("Array of documents to add"),
|
|
50
48
|
};
|
|
51
49
|
|
|
52
50
|
export const DeleteDocumentsSchema = {
|
|
53
51
|
collection: z.string().describe("Name of the collection"),
|
|
54
|
-
ids: z
|
|
55
|
-
.array(z.union([z.string(), z.number()]))
|
|
56
|
-
.describe("Array of document IDs to delete"),
|
|
52
|
+
ids: z.array(z.union([z.string(), z.number()])).describe("Array of document IDs to delete"),
|
|
57
53
|
};
|
|
58
54
|
|
|
59
55
|
// Search schemas
|
|
60
56
|
export const SemanticSearchSchema = {
|
|
61
57
|
collection: z.string().describe("Name of the collection to search"),
|
|
62
58
|
query: z.string().describe("Search query text"),
|
|
63
|
-
limit: z
|
|
64
|
-
|
|
65
|
-
.optional()
|
|
66
|
-
.describe("Maximum number of results (default: 5)"),
|
|
67
|
-
filter: z
|
|
68
|
-
.record(z.string(), z.any())
|
|
69
|
-
.optional()
|
|
70
|
-
.describe("Optional metadata filter"),
|
|
59
|
+
limit: z.number().optional().describe("Maximum number of results (default: 5)"),
|
|
60
|
+
filter: z.record(z.string(), z.any()).optional().describe("Optional metadata filter"),
|
|
71
61
|
};
|
|
72
62
|
|
|
73
63
|
export const HybridSearchSchema = {
|
|
74
64
|
collection: z.string().describe("Name of the collection to search"),
|
|
75
65
|
query: z.string().describe("Search query text"),
|
|
76
|
-
limit: z
|
|
77
|
-
|
|
78
|
-
.optional()
|
|
79
|
-
.describe("Maximum number of results (default: 5)"),
|
|
80
|
-
filter: z
|
|
81
|
-
.record(z.string(), z.any())
|
|
82
|
-
.optional()
|
|
83
|
-
.describe("Optional metadata filter"),
|
|
66
|
+
limit: z.number().optional().describe("Maximum number of results (default: 5)"),
|
|
67
|
+
filter: z.record(z.string(), z.any()).optional().describe("Optional metadata filter"),
|
|
84
68
|
};
|
|
85
69
|
|
|
86
70
|
// Code indexing schemas
|
|
87
71
|
export const IndexCodebaseSchema = {
|
|
88
|
-
path: z
|
|
89
|
-
.string()
|
|
90
|
-
.describe("Absolute or relative path to codebase root directory"),
|
|
72
|
+
path: z.string().describe("Absolute or relative path to codebase root directory"),
|
|
91
73
|
forceReindex: z
|
|
92
74
|
.boolean()
|
|
93
75
|
.optional()
|
|
@@ -99,20 +81,13 @@ export const IndexCodebaseSchema = {
|
|
|
99
81
|
ignorePatterns: z
|
|
100
82
|
.array(z.string())
|
|
101
83
|
.optional()
|
|
102
|
-
.describe(
|
|
103
|
-
"Additional patterns to ignore (e.g., ['**/test/**', '**/*.test.ts'])",
|
|
104
|
-
),
|
|
84
|
+
.describe("Additional patterns to ignore (e.g., ['**/test/**', '**/*.test.ts'])"),
|
|
105
85
|
};
|
|
106
86
|
|
|
107
87
|
export const SearchCodeSchema = {
|
|
108
88
|
path: z.string().describe("Path to codebase (must be indexed first)"),
|
|
109
|
-
query: z
|
|
110
|
-
|
|
111
|
-
.describe("Natural language search query (e.g., 'authentication logic')"),
|
|
112
|
-
limit: z
|
|
113
|
-
.number()
|
|
114
|
-
.optional()
|
|
115
|
-
.describe("Maximum number of results (default: 5, max: 100)"),
|
|
89
|
+
query: z.string().describe("Natural language search query (e.g., 'authentication logic')"),
|
|
90
|
+
limit: z.number().optional().describe("Maximum number of results (default: 5, max: 100)"),
|
|
116
91
|
fileTypes: z
|
|
117
92
|
.array(z.string())
|
|
118
93
|
.optional()
|
|
@@ -145,26 +120,16 @@ export const IndexGitHistorySchema = {
|
|
|
145
120
|
sinceDate: z
|
|
146
121
|
.string()
|
|
147
122
|
.optional()
|
|
148
|
-
.describe(
|
|
149
|
-
|
|
150
|
-
),
|
|
151
|
-
maxCommits: z
|
|
152
|
-
.number()
|
|
153
|
-
.optional()
|
|
154
|
-
.describe("Maximum number of commits to index (default: 5000)"),
|
|
123
|
+
.describe("Only index commits after this date (ISO format, e.g., '2024-01-01')"),
|
|
124
|
+
maxCommits: z.number().optional().describe("Maximum number of commits to index (default: 5000)"),
|
|
155
125
|
};
|
|
156
126
|
|
|
157
127
|
export const SearchGitHistorySchema = {
|
|
158
128
|
path: z.string().describe("Path to git repository (must be indexed first)"),
|
|
159
129
|
query: z
|
|
160
130
|
.string()
|
|
161
|
-
.describe(
|
|
162
|
-
|
|
163
|
-
),
|
|
164
|
-
limit: z
|
|
165
|
-
.number()
|
|
166
|
-
.optional()
|
|
167
|
-
.describe("Maximum number of results (default: 10, max: 100)"),
|
|
131
|
+
.describe("Natural language search query (e.g., 'fix null pointer in authentication')"),
|
|
132
|
+
limit: z.number().optional().describe("Maximum number of results (default: 10, max: 100)"),
|
|
168
133
|
commitTypes: z
|
|
169
134
|
.array(
|
|
170
135
|
z.enum([
|
|
@@ -180,22 +145,13 @@ export const SearchGitHistorySchema = {
|
|
|
180
145
|
"ci",
|
|
181
146
|
"revert",
|
|
182
147
|
"other",
|
|
183
|
-
])
|
|
148
|
+
])
|
|
184
149
|
)
|
|
185
150
|
.optional()
|
|
186
151
|
.describe("Filter by commit type (e.g., ['fix', 'feat'])"),
|
|
187
|
-
authors: z
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
.describe("Filter by author name or email"),
|
|
191
|
-
dateFrom: z
|
|
192
|
-
.string()
|
|
193
|
-
.optional()
|
|
194
|
-
.describe("Only commits after this date (ISO format)"),
|
|
195
|
-
dateTo: z
|
|
196
|
-
.string()
|
|
197
|
-
.optional()
|
|
198
|
-
.describe("Only commits before this date (ISO format)"),
|
|
152
|
+
authors: z.array(z.string()).optional().describe("Filter by author name or email"),
|
|
153
|
+
dateFrom: z.string().optional().describe("Only commits after this date (ISO format)"),
|
|
154
|
+
dateTo: z.string().optional().describe("Only commits before this date (ISO format)"),
|
|
199
155
|
};
|
|
200
156
|
|
|
201
157
|
export const IndexNewCommitsSchema = {
|
|
@@ -214,18 +170,10 @@ export const ClearGitIndexSchema = {
|
|
|
214
170
|
export const ContextualSearchSchema = {
|
|
215
171
|
path: z
|
|
216
172
|
.string()
|
|
217
|
-
.describe(
|
|
218
|
-
"Path to git repository (must be indexed for both code and git history)",
|
|
219
|
-
),
|
|
173
|
+
.describe("Path to git repository (must be indexed for both code and git history)"),
|
|
220
174
|
query: z.string().describe("Natural language search query"),
|
|
221
|
-
codeLimit: z
|
|
222
|
-
|
|
223
|
-
.optional()
|
|
224
|
-
.describe("Maximum number of code results (default: 5)"),
|
|
225
|
-
gitLimit: z
|
|
226
|
-
.number()
|
|
227
|
-
.optional()
|
|
228
|
-
.describe("Maximum number of git history results (default: 5)"),
|
|
175
|
+
codeLimit: z.number().optional().describe("Maximum number of code results (default: 5)"),
|
|
176
|
+
gitLimit: z.number().optional().describe("Maximum number of git history results (default: 5)"),
|
|
229
177
|
correlate: z
|
|
230
178
|
.boolean()
|
|
231
179
|
.optional()
|
|
@@ -239,10 +187,7 @@ export const FederatedSearchSchema = {
|
|
|
239
187
|
.min(1)
|
|
240
188
|
.describe("Array of repository paths to search (must all be indexed)"),
|
|
241
189
|
query: z.string().describe("Natural language search query"),
|
|
242
|
-
searchType: z
|
|
243
|
-
.enum(["code", "git", "both"])
|
|
244
|
-
.optional()
|
|
245
|
-
.describe("Type of search (default: both)"),
|
|
190
|
+
searchType: z.enum(["code", "git", "both"]).optional().describe("Type of search (default: both)"),
|
|
246
191
|
limit: z
|
|
247
192
|
.number()
|
|
248
193
|
.optional()
|
package/src/tools/search.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
|
-
import logger from "../logger.js";
|
|
7
6
|
import type { EmbeddingProvider } from "../embeddings/base.js";
|
|
8
7
|
import { BM25SparseVectorGenerator } from "../embeddings/sparse.js";
|
|
8
|
+
import logger from "../logger.js";
|
|
9
9
|
import type { QdrantManager } from "../qdrant/client.js";
|
|
10
10
|
import { withToolLogging } from "./logging.js";
|
|
11
11
|
import * as schemas from "./schemas.js";
|
|
@@ -17,10 +17,7 @@ export interface SearchToolDependencies {
|
|
|
17
17
|
embeddings: EmbeddingProvider;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function registerSearchTools(
|
|
21
|
-
server: McpServer,
|
|
22
|
-
deps: SearchToolDependencies,
|
|
23
|
-
): void {
|
|
20
|
+
export function registerSearchTools(server: McpServer, deps: SearchToolDependencies): void {
|
|
24
21
|
const { qdrant, embeddings } = deps;
|
|
25
22
|
|
|
26
23
|
// semantic_search
|
|
@@ -32,47 +29,39 @@ export function registerSearchTools(
|
|
|
32
29
|
"Search for documents using natural language queries. Returns the most semantically similar documents.",
|
|
33
30
|
inputSchema: schemas.SemanticSearchSchema,
|
|
34
31
|
},
|
|
35
|
-
withToolLogging(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
tool: "semantic_search",
|
|
41
|
-
collection,
|
|
42
|
-
query: query.substring(0, 80),
|
|
43
|
-
},
|
|
44
|
-
"Tool called",
|
|
45
|
-
);
|
|
46
|
-
// Check if collection exists
|
|
47
|
-
const exists = await qdrant.collectionExists(collection);
|
|
48
|
-
if (!exists) {
|
|
49
|
-
return {
|
|
50
|
-
content: [
|
|
51
|
-
{
|
|
52
|
-
type: "text",
|
|
53
|
-
text: `Error: Collection "${collection}" does not exist.`,
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
isError: true,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Generate embedding for query
|
|
61
|
-
const { embedding } = await embeddings.embed(query);
|
|
62
|
-
|
|
63
|
-
// Search
|
|
64
|
-
const results = await qdrant.search(
|
|
32
|
+
withToolLogging("semantic_search", async ({ collection, query, limit, filter }) => {
|
|
33
|
+
log.info(
|
|
34
|
+
{
|
|
35
|
+
tool: "semantic_search",
|
|
65
36
|
collection,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
37
|
+
query: query.substring(0, 80),
|
|
38
|
+
},
|
|
39
|
+
"Tool called"
|
|
40
|
+
);
|
|
41
|
+
// Check if collection exists
|
|
42
|
+
const exists = await qdrant.collectionExists(collection);
|
|
43
|
+
if (!exists) {
|
|
71
44
|
return {
|
|
72
|
-
content: [
|
|
45
|
+
content: [
|
|
46
|
+
{
|
|
47
|
+
type: "text",
|
|
48
|
+
text: `Error: Collection "${collection}" does not exist.`,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
isError: true,
|
|
73
52
|
};
|
|
74
|
-
}
|
|
75
|
-
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Generate embedding for query
|
|
56
|
+
const { embedding } = await embeddings.embed(query);
|
|
57
|
+
|
|
58
|
+
// Search
|
|
59
|
+
const results = await qdrant.search(collection, embedding, limit || 5, filter);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
63
|
+
};
|
|
64
|
+
})
|
|
76
65
|
);
|
|
77
66
|
|
|
78
67
|
// hybrid_search
|
|
@@ -84,61 +73,55 @@ export function registerSearchTools(
|
|
|
84
73
|
"Perform hybrid search combining semantic vector search with keyword search using BM25. This provides better results by combining the strengths of both approaches. The collection must be created with enableHybrid set to true.",
|
|
85
74
|
inputSchema: schemas.HybridSearchSchema,
|
|
86
75
|
},
|
|
87
|
-
withToolLogging(
|
|
88
|
-
"hybrid_search",
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
isError: true,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
76
|
+
withToolLogging("hybrid_search", async ({ collection, query, limit, filter }) => {
|
|
77
|
+
log.info({ tool: "hybrid_search", collection, query: query.substring(0, 80) }, "Tool called");
|
|
78
|
+
// Check if collection exists
|
|
79
|
+
const exists = await qdrant.collectionExists(collection);
|
|
80
|
+
if (!exists) {
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text",
|
|
85
|
+
text: `Error: Collection "${collection}" does not exist.`,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
isError: true,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
107
91
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
92
|
+
// Check if collection has hybrid search enabled
|
|
93
|
+
const collectionInfo = await qdrant.getCollectionInfo(collection);
|
|
94
|
+
if (!collectionInfo.hybridEnabled) {
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Error: Collection "${collection}" does not have hybrid search enabled. Create a new collection with enableHybrid set to true.`,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
isError: true,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
121
105
|
|
|
122
|
-
|
|
123
|
-
|
|
106
|
+
// Generate dense embedding for query
|
|
107
|
+
const { embedding } = await embeddings.embed(query);
|
|
124
108
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
109
|
+
// Generate sparse vector for query
|
|
110
|
+
const sparseGenerator = new BM25SparseVectorGenerator();
|
|
111
|
+
const sparseVector = sparseGenerator.generate(query);
|
|
128
112
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
113
|
+
// Perform hybrid search
|
|
114
|
+
const results = await qdrant.hybridSearch(
|
|
115
|
+
collection,
|
|
116
|
+
embedding,
|
|
117
|
+
sparseVector,
|
|
118
|
+
limit || 5,
|
|
119
|
+
filter
|
|
120
|
+
);
|
|
137
121
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
),
|
|
122
|
+
return {
|
|
123
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
124
|
+
};
|
|
125
|
+
})
|
|
143
126
|
);
|
|
144
127
|
}
|
|
@@ -126,10 +126,8 @@ def calculate_average(numbers):
|
|
|
126
126
|
if (chunks.length > 0) {
|
|
127
127
|
expect(
|
|
128
128
|
chunks.some(
|
|
129
|
-
(c) =>
|
|
130
|
-
|
|
131
|
-
c.metadata.name === "calculate_product",
|
|
132
|
-
),
|
|
129
|
+
(c) => c.metadata.name === "calculate_sum" || c.metadata.name === "calculate_product"
|
|
130
|
+
)
|
|
133
131
|
).toBe(true);
|
|
134
132
|
}
|
|
135
133
|
});
|
|
@@ -184,11 +182,7 @@ function veryLargeFunction() {
|
|
|
184
182
|
}
|
|
185
183
|
`;
|
|
186
184
|
|
|
187
|
-
const chunks = await chunker.chunk(
|
|
188
|
-
largeFunction,
|
|
189
|
-
"test.js",
|
|
190
|
-
"javascript",
|
|
191
|
-
);
|
|
185
|
+
const chunks = await chunker.chunk(largeFunction, "test.js", "javascript");
|
|
192
186
|
expect(chunks.length).toBeGreaterThan(0);
|
|
193
187
|
});
|
|
194
188
|
|
|
@@ -216,13 +210,8 @@ function myFunction() {
|
|
|
216
210
|
});
|
|
217
211
|
|
|
218
212
|
it("should include file path and language", async () => {
|
|
219
|
-
const code =
|
|
220
|
-
|
|
221
|
-
const chunks = await chunker.chunk(
|
|
222
|
-
code,
|
|
223
|
-
"/path/to/file.ts",
|
|
224
|
-
"typescript",
|
|
225
|
-
);
|
|
213
|
+
const code = "function test() {\n console.log('Test function');\n return true;\n}";
|
|
214
|
+
const chunks = await chunker.chunk(code, "/path/to/file.ts", "typescript");
|
|
226
215
|
|
|
227
216
|
expect(chunks[0].metadata.filePath).toBe("/path/to/file.ts");
|
|
228
217
|
expect(chunks[0].metadata.language).toBe("typescript");
|
|
@@ -337,9 +326,7 @@ trait Printable {
|
|
|
337
326
|
expect(chunks.length).toBeGreaterThanOrEqual(0);
|
|
338
327
|
// Should classify as interface type due to trait pattern
|
|
339
328
|
if (chunks.length > 0) {
|
|
340
|
-
expect(chunks.some((c) => c.metadata.chunkType === "interface")).toBe(
|
|
341
|
-
true,
|
|
342
|
-
);
|
|
329
|
+
expect(chunks.some((c) => c.metadata.chunkType === "interface")).toBe(true);
|
|
343
330
|
}
|
|
344
331
|
});
|
|
345
332
|
|