@milo4jo/contextkit 0.1.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/README.md +181 -0
- package/dist/commands/index-cmd.d.ts +3 -0
- package/dist/commands/index-cmd.d.ts.map +1 -0
- package/dist/commands/index-cmd.js +111 -0
- package/dist/commands/index-cmd.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +56 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/select.d.ts +3 -0
- package/dist/commands/select.d.ts.map +1 -0
- package/dist/commands/select.js +64 -0
- package/dist/commands/select.js.map +1 -0
- package/dist/commands/source/add.d.ts +3 -0
- package/dist/commands/source/add.d.ts.map +1 -0
- package/dist/commands/source/add.js +87 -0
- package/dist/commands/source/add.js.map +1 -0
- package/dist/commands/source/index.d.ts +3 -0
- package/dist/commands/source/index.d.ts.map +1 -0
- package/dist/commands/source/index.js +14 -0
- package/dist/commands/source/index.js.map +1 -0
- package/dist/commands/source/list.d.ts +3 -0
- package/dist/commands/source/list.d.ts.map +1 -0
- package/dist/commands/source/list.js +46 -0
- package/dist/commands/source/list.js.map +1 -0
- package/dist/commands/source/remove.d.ts +3 -0
- package/dist/commands/source/remove.d.ts.map +1 -0
- package/dist/commands/source/remove.js +38 -0
- package/dist/commands/source/remove.js.map +1 -0
- package/dist/commands/source.d.ts +3 -0
- package/dist/commands/source.d.ts.map +1 -0
- package/dist/commands/source.js +153 -0
- package/dist/commands/source.js.map +1 -0
- package/dist/config/index.d.ts +38 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +100 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +21 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/db/index.d.ts +14 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +63 -0
- package/dist/db/index.js.map +1 -0
- package/dist/errors/index.d.ts +30 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +51 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/chunker.d.ts +44 -0
- package/dist/indexer/chunker.d.ts.map +1 -0
- package/dist/indexer/chunker.js +102 -0
- package/dist/indexer/chunker.js.map +1 -0
- package/dist/indexer/discovery.d.ts +34 -0
- package/dist/indexer/discovery.d.ts.map +1 -0
- package/dist/indexer/discovery.js +66 -0
- package/dist/indexer/discovery.js.map +1 -0
- package/dist/indexer/embeddings.d.ts +32 -0
- package/dist/indexer/embeddings.d.ts.map +1 -0
- package/dist/indexer/embeddings.js +85 -0
- package/dist/indexer/embeddings.js.map +1 -0
- package/dist/indexer/index.d.ts +37 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +123 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/selector/budget.d.ts +26 -0
- package/dist/selector/budget.d.ts.map +1 -0
- package/dist/selector/budget.js +75 -0
- package/dist/selector/budget.js.map +1 -0
- package/dist/selector/formatter.d.ts +44 -0
- package/dist/selector/formatter.d.ts.map +1 -0
- package/dist/selector/formatter.js +114 -0
- package/dist/selector/formatter.js.map +1 -0
- package/dist/selector/index.d.ts +37 -0
- package/dist/selector/index.d.ts.map +1 -0
- package/dist/selector/index.js +67 -0
- package/dist/selector/index.js.map +1 -0
- package/dist/selector/scoring.d.ts +26 -0
- package/dist/selector/scoring.d.ts.map +1 -0
- package/dist/selector/scoring.js +113 -0
- package/dist/selector/scoring.js.map +1 -0
- package/dist/selector/search.d.ts +29 -0
- package/dist/selector/search.d.ts.map +1 -0
- package/dist/selector/search.js +48 -0
- package/dist/selector/search.js.map +1 -0
- package/dist/utils/cli.d.ts +20 -0
- package/dist/utils/cli.d.ts.map +1 -0
- package/dist/utils/cli.js +19 -0
- package/dist/utils/cli.js.map +1 -0
- package/dist/utils/format.d.ts +30 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +44 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/output.d.ts +42 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +62 -0
- package/dist/utils/output.js.map +1 -0
- package/dist/utils/prompts.d.ts +23 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +46 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/streams.d.ts +40 -0
- package/dist/utils/streams.d.ts.map +1 -0
- package/dist/utils/streams.js +61 -0
- package/dist/utils/streams.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Budget Fitting Module
|
|
3
|
+
*
|
|
4
|
+
* Selects chunks to fit within a token budget.
|
|
5
|
+
* Prefers keeping chunks from the same file together.
|
|
6
|
+
*/
|
|
7
|
+
import type { RankedChunk } from './scoring.js';
|
|
8
|
+
/** Selection result */
|
|
9
|
+
export interface BudgetResult {
|
|
10
|
+
/** Selected chunks */
|
|
11
|
+
chunks: RankedChunk[];
|
|
12
|
+
/** Total tokens used */
|
|
13
|
+
totalTokens: number;
|
|
14
|
+
/** Chunks that didn't fit */
|
|
15
|
+
excluded: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Select chunks that fit within budget
|
|
19
|
+
*/
|
|
20
|
+
export declare function fitToBudget(chunks: RankedChunk[], budget: number): BudgetResult;
|
|
21
|
+
/**
|
|
22
|
+
* Merge adjacent chunks from the same file
|
|
23
|
+
* (Optional optimization for cleaner output)
|
|
24
|
+
*/
|
|
25
|
+
export declare function mergeAdjacentChunks(chunks: RankedChunk[]): RankedChunk[];
|
|
26
|
+
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/selector/budget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,uBAAuB;AACvB,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAsC/E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CA8BxE"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Budget Fitting Module
|
|
3
|
+
*
|
|
4
|
+
* Selects chunks to fit within a token budget.
|
|
5
|
+
* Prefers keeping chunks from the same file together.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Select chunks that fit within budget
|
|
9
|
+
*/
|
|
10
|
+
export function fitToBudget(chunks, budget) {
|
|
11
|
+
const selected = [];
|
|
12
|
+
let totalTokens = 0;
|
|
13
|
+
let excluded = 0;
|
|
14
|
+
// Track which files we've started including
|
|
15
|
+
const includedFiles = new Set();
|
|
16
|
+
for (const chunk of chunks) {
|
|
17
|
+
const wouldExceed = totalTokens + chunk.tokens > budget;
|
|
18
|
+
if (wouldExceed) {
|
|
19
|
+
excluded++;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
// Bonus: if we've already included chunks from this file,
|
|
23
|
+
// slightly prefer including more from the same file
|
|
24
|
+
// (This is handled implicitly by processing in score order,
|
|
25
|
+
// but we could add explicit grouping here later)
|
|
26
|
+
selected.push(chunk);
|
|
27
|
+
totalTokens += chunk.tokens;
|
|
28
|
+
includedFiles.add(chunk.filePath);
|
|
29
|
+
}
|
|
30
|
+
// Re-sort selected chunks by file, then by line number for output
|
|
31
|
+
selected.sort((a, b) => {
|
|
32
|
+
const fileCompare = a.filePath.localeCompare(b.filePath);
|
|
33
|
+
if (fileCompare !== 0)
|
|
34
|
+
return fileCompare;
|
|
35
|
+
return a.startLine - b.startLine;
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
chunks: selected,
|
|
39
|
+
totalTokens,
|
|
40
|
+
excluded,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Merge adjacent chunks from the same file
|
|
45
|
+
* (Optional optimization for cleaner output)
|
|
46
|
+
*/
|
|
47
|
+
export function mergeAdjacentChunks(chunks) {
|
|
48
|
+
if (chunks.length <= 1)
|
|
49
|
+
return chunks;
|
|
50
|
+
const merged = [];
|
|
51
|
+
let current = { ...chunks[0] };
|
|
52
|
+
for (let i = 1; i < chunks.length; i++) {
|
|
53
|
+
const next = chunks[i];
|
|
54
|
+
// Check if adjacent (same file, consecutive lines)
|
|
55
|
+
const isAdjacent = current.filePath === next.filePath && current.endLine + 1 >= next.startLine;
|
|
56
|
+
if (isAdjacent) {
|
|
57
|
+
// Merge chunks
|
|
58
|
+
current = {
|
|
59
|
+
...current,
|
|
60
|
+
content: current.content + '\n' + next.content,
|
|
61
|
+
endLine: next.endLine,
|
|
62
|
+
tokens: current.tokens + next.tokens,
|
|
63
|
+
score: Math.max(current.score, next.score),
|
|
64
|
+
similarity: Math.max(current.similarity, next.similarity),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
merged.push(current);
|
|
69
|
+
current = { ...next };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
merged.push(current);
|
|
73
|
+
return merged;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/selector/budget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAqB,EAAE,MAAc;IAC/D,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,4CAA4C;IAC5C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IAExC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QAExD,IAAI,WAAW,EAAE,CAAC;YAChB,QAAQ,EAAE,CAAC;YACX,SAAS;QACX,CAAC;QAED,0DAA0D;QAC1D,oDAAoD;QACpD,4DAA4D;QAC5D,iDAAiD;QAEjD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC;QAC5B,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrB,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,WAAW,KAAK,CAAC;YAAE,OAAO,WAAW,CAAC;QAC1C,OAAO,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,QAAQ;QAChB,WAAW;QACX,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAqB;IACvD,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAEtC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,IAAI,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAEvB,mDAAmD;QACnD,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC;QAE/F,IAAI,UAAU,EAAE,CAAC;YACf,eAAe;YACf,OAAO,GAAG;gBACR,GAAG,OAAO;gBACV,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,OAAO;gBAC9C,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;gBACpC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;gBAC1C,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC;aAC1D,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output Formatter Module
|
|
3
|
+
*
|
|
4
|
+
* Formats selected chunks for display.
|
|
5
|
+
*/
|
|
6
|
+
import type { BudgetResult } from './budget.js';
|
|
7
|
+
/** Formatted output */
|
|
8
|
+
export interface FormattedOutput {
|
|
9
|
+
/** Human-readable text output */
|
|
10
|
+
text: string;
|
|
11
|
+
/** Structured data for JSON output */
|
|
12
|
+
data: SelectionData;
|
|
13
|
+
}
|
|
14
|
+
/** Structured selection data */
|
|
15
|
+
export interface SelectionData {
|
|
16
|
+
query: string;
|
|
17
|
+
context: string;
|
|
18
|
+
chunks: ChunkInfo[];
|
|
19
|
+
stats: SelectionStats;
|
|
20
|
+
}
|
|
21
|
+
/** Chunk info for JSON output */
|
|
22
|
+
export interface ChunkInfo {
|
|
23
|
+
file: string;
|
|
24
|
+
lines: [number, number];
|
|
25
|
+
tokens: number;
|
|
26
|
+
score: number;
|
|
27
|
+
}
|
|
28
|
+
/** Selection statistics */
|
|
29
|
+
export interface SelectionStats {
|
|
30
|
+
totalTokens: number;
|
|
31
|
+
chunksConsidered: number;
|
|
32
|
+
chunksIncluded: number;
|
|
33
|
+
filesIncluded: number;
|
|
34
|
+
timeMs: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Format selection results for output
|
|
38
|
+
*/
|
|
39
|
+
export declare function formatOutput(query: string, result: BudgetResult, totalConsidered: number, timeMs: number): FormattedOutput;
|
|
40
|
+
/**
|
|
41
|
+
* Format output with --explain details
|
|
42
|
+
*/
|
|
43
|
+
export declare function formatWithExplanation(query: string, result: BudgetResult, totalConsidered: number, timeMs: number): FormattedOutput;
|
|
44
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/selector/formatter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,uBAAuB;AACvB,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,iCAAiC;AACjC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,YAAY,EACpB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,GACb,eAAe,CAqDjB;AA8CD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,YAAY,EACpB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,GACb,eAAe,CAmBjB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output Formatter Module
|
|
3
|
+
*
|
|
4
|
+
* Formats selected chunks for display.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Format selection results for output
|
|
8
|
+
*/
|
|
9
|
+
export function formatOutput(query, result, totalConsidered, timeMs) {
|
|
10
|
+
const { chunks, totalTokens } = result;
|
|
11
|
+
// Group chunks by file
|
|
12
|
+
const fileGroups = new Map();
|
|
13
|
+
for (const chunk of chunks) {
|
|
14
|
+
const existing = fileGroups.get(chunk.filePath) || [];
|
|
15
|
+
existing.push(chunk);
|
|
16
|
+
fileGroups.set(chunk.filePath, existing);
|
|
17
|
+
}
|
|
18
|
+
// Build text output
|
|
19
|
+
const textParts = [];
|
|
20
|
+
for (const [filePath, fileChunks] of fileGroups) {
|
|
21
|
+
// Sort chunks by line number within file
|
|
22
|
+
fileChunks.sort((a, b) => a.startLine - b.startLine);
|
|
23
|
+
for (const chunk of fileChunks) {
|
|
24
|
+
const header = `## ${filePath} (lines ${chunk.startLine}-${chunk.endLine})`;
|
|
25
|
+
const codeBlock = formatCodeBlock(chunk.content, filePath);
|
|
26
|
+
textParts.push(`${header}\n${codeBlock}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Add stats footer
|
|
30
|
+
const filesCount = fileGroups.size;
|
|
31
|
+
const statsLine = `📊 ${totalTokens.toLocaleString()} tokens | ${chunks.length} chunks | ${filesCount} files`;
|
|
32
|
+
const text = textParts.join('\n\n') + '\n\n---\n' + statsLine;
|
|
33
|
+
// Build structured data
|
|
34
|
+
const chunkInfos = chunks.map((c) => ({
|
|
35
|
+
file: c.filePath,
|
|
36
|
+
lines: [c.startLine, c.endLine],
|
|
37
|
+
tokens: c.tokens,
|
|
38
|
+
score: Math.round(c.score * 1000) / 1000,
|
|
39
|
+
}));
|
|
40
|
+
const data = {
|
|
41
|
+
query,
|
|
42
|
+
context: textParts.join('\n\n'),
|
|
43
|
+
chunks: chunkInfos,
|
|
44
|
+
stats: {
|
|
45
|
+
totalTokens,
|
|
46
|
+
chunksConsidered: totalConsidered,
|
|
47
|
+
chunksIncluded: chunks.length,
|
|
48
|
+
filesIncluded: filesCount,
|
|
49
|
+
timeMs,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
return { text, data };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Format content as a code block with language hint
|
|
56
|
+
*/
|
|
57
|
+
function formatCodeBlock(content, filePath) {
|
|
58
|
+
const lang = getLanguage(filePath);
|
|
59
|
+
return '```' + lang + '\n' + content + '\n```';
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get language hint from file extension
|
|
63
|
+
*/
|
|
64
|
+
function getLanguage(filePath) {
|
|
65
|
+
const ext = filePath.split('.').pop()?.toLowerCase() || '';
|
|
66
|
+
const langMap = {
|
|
67
|
+
ts: 'typescript',
|
|
68
|
+
tsx: 'tsx',
|
|
69
|
+
js: 'javascript',
|
|
70
|
+
jsx: 'jsx',
|
|
71
|
+
py: 'python',
|
|
72
|
+
rb: 'ruby',
|
|
73
|
+
go: 'go',
|
|
74
|
+
rs: 'rust',
|
|
75
|
+
java: 'java',
|
|
76
|
+
kt: 'kotlin',
|
|
77
|
+
cs: 'csharp',
|
|
78
|
+
cpp: 'cpp',
|
|
79
|
+
c: 'c',
|
|
80
|
+
h: 'c',
|
|
81
|
+
hpp: 'cpp',
|
|
82
|
+
md: 'markdown',
|
|
83
|
+
json: 'json',
|
|
84
|
+
yaml: 'yaml',
|
|
85
|
+
yml: 'yaml',
|
|
86
|
+
toml: 'toml',
|
|
87
|
+
sql: 'sql',
|
|
88
|
+
sh: 'bash',
|
|
89
|
+
bash: 'bash',
|
|
90
|
+
zsh: 'bash',
|
|
91
|
+
};
|
|
92
|
+
return langMap[ext] || '';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Format output with --explain details
|
|
96
|
+
*/
|
|
97
|
+
export function formatWithExplanation(query, result, totalConsidered, timeMs) {
|
|
98
|
+
const base = formatOutput(query, result, totalConsidered, timeMs);
|
|
99
|
+
// Add explanation section
|
|
100
|
+
const explanations = result.chunks.map((chunk) => {
|
|
101
|
+
const { similarity, recency, pathMatch } = chunk.scoreBreakdown;
|
|
102
|
+
return ` ${chunk.filePath}:${chunk.startLine}
|
|
103
|
+
similarity: ${(similarity * 100).toFixed(1)}%
|
|
104
|
+
recency: ${(recency * 100).toFixed(1)}%
|
|
105
|
+
path_match: ${(pathMatch * 100).toFixed(1)}%
|
|
106
|
+
→ score: ${(chunk.score * 100).toFixed(1)}%`;
|
|
107
|
+
});
|
|
108
|
+
const explainSection = '\n\n## Scoring Details\n\n' + explanations.join('\n\n');
|
|
109
|
+
return {
|
|
110
|
+
text: base.text + explainSection,
|
|
111
|
+
data: base.data,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/selector/formatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main Selector Module
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the selection pipeline:
|
|
5
|
+
* 1. Search for similar chunks
|
|
6
|
+
* 2. Score and rank
|
|
7
|
+
* 3. Fit to budget
|
|
8
|
+
* 4. Format output
|
|
9
|
+
*/
|
|
10
|
+
import Database from 'better-sqlite3';
|
|
11
|
+
import { type FormattedOutput } from './formatter.js';
|
|
12
|
+
/** Selection options */
|
|
13
|
+
export interface SelectOptions {
|
|
14
|
+
/** Query to find context for */
|
|
15
|
+
query: string;
|
|
16
|
+
/** Maximum tokens to include */
|
|
17
|
+
budget: number;
|
|
18
|
+
/** Filter to specific sources */
|
|
19
|
+
sources?: string[];
|
|
20
|
+
/** Show scoring explanation */
|
|
21
|
+
explain?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Selection result */
|
|
24
|
+
export interface SelectResult {
|
|
25
|
+
/** Formatted output */
|
|
26
|
+
output: FormattedOutput;
|
|
27
|
+
/** Whether index is empty */
|
|
28
|
+
isEmpty: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Select optimal context for a query
|
|
32
|
+
*/
|
|
33
|
+
export declare function selectContext(db: Database.Database, options: SelectOptions): Promise<SelectResult>;
|
|
34
|
+
export type { FormattedOutput, SelectionData, SelectionStats, ChunkInfo } from './formatter.js';
|
|
35
|
+
export type { ScoredChunk } from './search.js';
|
|
36
|
+
export type { RankedChunk } from './scoring.js';
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/selector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,OAAO,EAAuC,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE3F,wBAAwB;AACxB,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,uBAAuB;AACvB,MAAM,WAAW,YAAY;IAC3B,uBAAuB;IACvB,MAAM,EAAE,eAAe,CAAC;IACxB,6BAA6B;IAC7B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAwDvB;AAGD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChG,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main Selector Module
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the selection pipeline:
|
|
5
|
+
* 1. Search for similar chunks
|
|
6
|
+
* 2. Score and rank
|
|
7
|
+
* 3. Fit to budget
|
|
8
|
+
* 4. Format output
|
|
9
|
+
*/
|
|
10
|
+
import { searchSimilar } from './search.js';
|
|
11
|
+
import { rankChunks } from './scoring.js';
|
|
12
|
+
import { fitToBudget, mergeAdjacentChunks } from './budget.js';
|
|
13
|
+
import { formatOutput, formatWithExplanation } from './formatter.js';
|
|
14
|
+
/**
|
|
15
|
+
* Select optimal context for a query
|
|
16
|
+
*/
|
|
17
|
+
export async function selectContext(db, options) {
|
|
18
|
+
const startTime = Date.now();
|
|
19
|
+
// Check if index has any chunks
|
|
20
|
+
const countResult = db.prepare('SELECT COUNT(*) as count FROM chunks').get();
|
|
21
|
+
if (countResult.count === 0) {
|
|
22
|
+
return {
|
|
23
|
+
output: {
|
|
24
|
+
text: '',
|
|
25
|
+
data: {
|
|
26
|
+
query: options.query,
|
|
27
|
+
context: '',
|
|
28
|
+
chunks: [],
|
|
29
|
+
stats: {
|
|
30
|
+
totalTokens: 0,
|
|
31
|
+
chunksConsidered: 0,
|
|
32
|
+
chunksIncluded: 0,
|
|
33
|
+
filesIncluded: 0,
|
|
34
|
+
timeMs: 0,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
isEmpty: true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// Step 1: Search for similar chunks
|
|
42
|
+
const searchOpts = {
|
|
43
|
+
limit: 50,
|
|
44
|
+
sources: options.sources,
|
|
45
|
+
};
|
|
46
|
+
const similarChunks = await searchSimilar(db, options.query, searchOpts);
|
|
47
|
+
// Step 2: Score and rank
|
|
48
|
+
const rankedChunks = rankChunks(similarChunks, options.query);
|
|
49
|
+
// Step 3: Fit to budget
|
|
50
|
+
const budgetResult = fitToBudget(rankedChunks, options.budget);
|
|
51
|
+
// Step 4: Merge adjacent chunks for cleaner output
|
|
52
|
+
const mergedChunks = mergeAdjacentChunks(budgetResult.chunks);
|
|
53
|
+
const mergedResult = {
|
|
54
|
+
...budgetResult,
|
|
55
|
+
chunks: mergedChunks,
|
|
56
|
+
};
|
|
57
|
+
// Step 5: Format output
|
|
58
|
+
const timeMs = Date.now() - startTime;
|
|
59
|
+
const output = options.explain
|
|
60
|
+
? formatWithExplanation(options.query, mergedResult, similarChunks.length, timeMs)
|
|
61
|
+
: formatOutput(options.query, mergedResult, similarChunks.length, timeMs);
|
|
62
|
+
return {
|
|
63
|
+
output,
|
|
64
|
+
isEmpty: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/selector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAwB,MAAM,gBAAgB,CAAC;AAsB3F;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAqB,EACrB,OAAsB;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,gCAAgC;IAChC,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC,GAAG,EAAuB,CAAC;IAClG,IAAI,WAAW,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,MAAM,EAAE;gBACN,IAAI,EAAE,EAAE;gBACR,IAAI,EAAE;oBACJ,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,OAAO,EAAE,EAAE;oBACX,MAAM,EAAE,EAAE;oBACV,KAAK,EAAE;wBACL,WAAW,EAAE,CAAC;wBACd,gBAAgB,EAAE,CAAC;wBACnB,cAAc,EAAE,CAAC;wBACjB,aAAa,EAAE,CAAC;wBAChB,MAAM,EAAE,CAAC;qBACV;iBACF;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,oCAAoC;IACpC,MAAM,UAAU,GAAkB;QAChC,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC;IACF,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAEzE,yBAAyB;IACzB,MAAM,YAAY,GAAG,UAAU,CAAC,aAAa,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAE9D,wBAAwB;IACxB,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/D,mDAAmD;IACnD,MAAM,YAAY,GAAG,mBAAmB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG;QACnB,GAAG,YAAY;QACf,MAAM,EAAE,YAAY;KACrB,CAAC;IAEF,wBAAwB;IACxB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACtC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO;QAC5B,CAAC,CAAC,qBAAqB,CAAC,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC;QAClF,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE5E,OAAO;QACL,MAAM;QACN,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoring Module
|
|
3
|
+
*
|
|
4
|
+
* Calculates final scores for chunks based on multiple signals.
|
|
5
|
+
*
|
|
6
|
+
* Score = 0.6 × semantic_similarity
|
|
7
|
+
* + 0.2 × recency_bonus
|
|
8
|
+
* + 0.2 × path_match_bonus
|
|
9
|
+
*/
|
|
10
|
+
import type { ScoredChunk } from './search.js';
|
|
11
|
+
/** Chunk with final score */
|
|
12
|
+
export interface RankedChunk extends ScoredChunk {
|
|
13
|
+
/** Final combined score */
|
|
14
|
+
score: number;
|
|
15
|
+
/** Individual score components for --explain */
|
|
16
|
+
scoreBreakdown: {
|
|
17
|
+
similarity: number;
|
|
18
|
+
recency: number;
|
|
19
|
+
pathMatch: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Calculate scores and rank chunks
|
|
24
|
+
*/
|
|
25
|
+
export declare function rankChunks(chunks: ScoredChunk[], query: string): RankedChunk[];
|
|
26
|
+
//# sourceMappingURL=scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../../src/selector/scoring.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,6BAA6B;AAC7B,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,cAAc,EAAE;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AASD;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAqC9E"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoring Module
|
|
3
|
+
*
|
|
4
|
+
* Calculates final scores for chunks based on multiple signals.
|
|
5
|
+
*
|
|
6
|
+
* Score = 0.6 × semantic_similarity
|
|
7
|
+
* + 0.2 × recency_bonus
|
|
8
|
+
* + 0.2 × path_match_bonus
|
|
9
|
+
*/
|
|
10
|
+
/** Scoring weights */
|
|
11
|
+
const WEIGHTS = {
|
|
12
|
+
similarity: 0.6,
|
|
13
|
+
recency: 0.2,
|
|
14
|
+
pathMatch: 0.2,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Calculate scores and rank chunks
|
|
18
|
+
*/
|
|
19
|
+
export function rankChunks(chunks, query) {
|
|
20
|
+
// Extract keywords from query for path matching
|
|
21
|
+
const queryKeywords = extractKeywords(query);
|
|
22
|
+
// Find max/min for normalization (recency not used yet since we don't track it)
|
|
23
|
+
const ranked = chunks.map((chunk) => {
|
|
24
|
+
// Semantic similarity (already 0-1)
|
|
25
|
+
const similarityScore = chunk.similarity;
|
|
26
|
+
// Recency bonus (placeholder - would use indexed_at if we tracked per-chunk)
|
|
27
|
+
// For now, give all chunks equal recency
|
|
28
|
+
const recencyScore = 0.5;
|
|
29
|
+
// Path match bonus
|
|
30
|
+
const pathMatchScore = calculatePathMatch(chunk.filePath, queryKeywords);
|
|
31
|
+
// Combined score
|
|
32
|
+
const score = WEIGHTS.similarity * similarityScore +
|
|
33
|
+
WEIGHTS.recency * recencyScore +
|
|
34
|
+
WEIGHTS.pathMatch * pathMatchScore;
|
|
35
|
+
return {
|
|
36
|
+
...chunk,
|
|
37
|
+
score,
|
|
38
|
+
scoreBreakdown: {
|
|
39
|
+
similarity: similarityScore,
|
|
40
|
+
recency: recencyScore,
|
|
41
|
+
pathMatch: pathMatchScore,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
// Sort by final score descending
|
|
46
|
+
ranked.sort((a, b) => b.score - a.score);
|
|
47
|
+
return ranked;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Extract keywords from query for path matching
|
|
51
|
+
*/
|
|
52
|
+
function extractKeywords(query) {
|
|
53
|
+
return query
|
|
54
|
+
.toLowerCase()
|
|
55
|
+
.split(/\s+/)
|
|
56
|
+
.filter((word) => word.length > 2)
|
|
57
|
+
.filter((word) => !STOP_WORDS.has(word));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Calculate path match score (0-1)
|
|
61
|
+
*/
|
|
62
|
+
function calculatePathMatch(filePath, keywords) {
|
|
63
|
+
if (keywords.length === 0)
|
|
64
|
+
return 0;
|
|
65
|
+
const pathLower = filePath.toLowerCase();
|
|
66
|
+
let matches = 0;
|
|
67
|
+
for (const keyword of keywords) {
|
|
68
|
+
if (pathLower.includes(keyword)) {
|
|
69
|
+
matches++;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return matches / keywords.length;
|
|
73
|
+
}
|
|
74
|
+
/** Common words to ignore in path matching */
|
|
75
|
+
const STOP_WORDS = new Set([
|
|
76
|
+
'the',
|
|
77
|
+
'a',
|
|
78
|
+
'an',
|
|
79
|
+
'is',
|
|
80
|
+
'are',
|
|
81
|
+
'was',
|
|
82
|
+
'were',
|
|
83
|
+
'be',
|
|
84
|
+
'been',
|
|
85
|
+
'how',
|
|
86
|
+
'what',
|
|
87
|
+
'where',
|
|
88
|
+
'when',
|
|
89
|
+
'why',
|
|
90
|
+
'who',
|
|
91
|
+
'which',
|
|
92
|
+
'does',
|
|
93
|
+
'do',
|
|
94
|
+
'did',
|
|
95
|
+
'has',
|
|
96
|
+
'have',
|
|
97
|
+
'had',
|
|
98
|
+
'this',
|
|
99
|
+
'that',
|
|
100
|
+
'these',
|
|
101
|
+
'those',
|
|
102
|
+
'and',
|
|
103
|
+
'or',
|
|
104
|
+
'but',
|
|
105
|
+
'not',
|
|
106
|
+
'with',
|
|
107
|
+
'for',
|
|
108
|
+
'from',
|
|
109
|
+
'to',
|
|
110
|
+
'in',
|
|
111
|
+
'on',
|
|
112
|
+
]);
|
|
113
|
+
//# sourceMappingURL=scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../src/selector/scoring.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH,sBAAsB;AACtB,MAAM,OAAO,GAAG;IACd,UAAU,EAAE,GAAG;IACf,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAqB,EAAE,KAAa;IAC7D,gDAAgD;IAChD,MAAM,aAAa,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAE7C,gFAAgF;IAChF,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAClC,oCAAoC;QACpC,MAAM,eAAe,GAAG,KAAK,CAAC,UAAU,CAAC;QAEzC,6EAA6E;QAC7E,yCAAyC;QACzC,MAAM,YAAY,GAAG,GAAG,CAAC;QAEzB,mBAAmB;QACnB,MAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAEzE,iBAAiB;QACjB,MAAM,KAAK,GACT,OAAO,CAAC,UAAU,GAAG,eAAe;YACpC,OAAO,CAAC,OAAO,GAAG,YAAY;YAC9B,OAAO,CAAC,SAAS,GAAG,cAAc,CAAC;QAErC,OAAO;YACL,GAAG,KAAK;YACR,KAAK;YACL,cAAc,EAAE;gBACd,UAAU,EAAE,eAAe;gBAC3B,OAAO,EAAE,YAAY;gBACrB,SAAS,EAAE,cAAc;aAC1B;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,iCAAiC;IACjC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAEzC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,KAAK;SACT,WAAW,EAAE;SACb,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SACjC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,QAAgB,EAAE,QAAkB;IAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACzC,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,OAAO,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC;AACnC,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,KAAK;IACL,GAAG;IACH,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,KAAK;IACL,MAAM;IACN,IAAI;IACJ,MAAM;IACN,KAAK;IACL,MAAM;IACN,OAAO;IACP,MAAM;IACN,KAAK;IACL,KAAK;IACL,OAAO;IACP,MAAM;IACN,IAAI;IACJ,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,KAAK;IACL,IAAI;IACJ,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;CACL,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Similarity Search Module
|
|
3
|
+
*
|
|
4
|
+
* Finds chunks most similar to a query using cosine similarity.
|
|
5
|
+
*/
|
|
6
|
+
import Database from 'better-sqlite3';
|
|
7
|
+
/** Chunk from database with similarity score */
|
|
8
|
+
export interface ScoredChunk {
|
|
9
|
+
id: string;
|
|
10
|
+
sourceId: string;
|
|
11
|
+
filePath: string;
|
|
12
|
+
content: string;
|
|
13
|
+
startLine: number;
|
|
14
|
+
endLine: number;
|
|
15
|
+
tokens: number;
|
|
16
|
+
similarity: number;
|
|
17
|
+
}
|
|
18
|
+
/** Search options */
|
|
19
|
+
export interface SearchOptions {
|
|
20
|
+
/** Maximum chunks to retrieve */
|
|
21
|
+
limit?: number;
|
|
22
|
+
/** Filter to specific sources */
|
|
23
|
+
sources?: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Search for chunks similar to a query
|
|
27
|
+
*/
|
|
28
|
+
export declare function searchSimilar(db: Database.Database, query: string, options?: SearchOptions): Promise<ScoredChunk[]>;
|
|
29
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/selector/search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAqB;AACrB,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAID;;GAEG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,WAAW,EAAE,CAAC,CAqDxB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Similarity Search Module
|
|
3
|
+
*
|
|
4
|
+
* Finds chunks most similar to a query using cosine similarity.
|
|
5
|
+
*/
|
|
6
|
+
import { embed, cosineSimilarity } from '../indexer/embeddings.js';
|
|
7
|
+
import { readEmbedding } from '../indexer/index.js';
|
|
8
|
+
const DEFAULT_LIMIT = 50;
|
|
9
|
+
/**
|
|
10
|
+
* Search for chunks similar to a query
|
|
11
|
+
*/
|
|
12
|
+
export async function searchSimilar(db, query, options = {}) {
|
|
13
|
+
const limit = options.limit || DEFAULT_LIMIT;
|
|
14
|
+
// Embed the query
|
|
15
|
+
const queryEmbedding = await embed(query);
|
|
16
|
+
// Build SQL query
|
|
17
|
+
let sql = `
|
|
18
|
+
SELECT id, source_id, file_path, content, start_line, end_line, tokens, embedding
|
|
19
|
+
FROM chunks
|
|
20
|
+
`;
|
|
21
|
+
const params = [];
|
|
22
|
+
if (options.sources && options.sources.length > 0) {
|
|
23
|
+
const placeholders = options.sources.map(() => '?').join(', ');
|
|
24
|
+
sql += ` WHERE source_id IN (${placeholders})`;
|
|
25
|
+
params.push(...options.sources);
|
|
26
|
+
}
|
|
27
|
+
// Get all chunks (we'll sort in JS for cosine similarity)
|
|
28
|
+
const rows = db.prepare(sql).all(...params);
|
|
29
|
+
// Calculate similarity for each chunk
|
|
30
|
+
const scored = rows.map((row) => {
|
|
31
|
+
const chunkEmbedding = readEmbedding(row.embedding);
|
|
32
|
+
const similarity = cosineSimilarity(queryEmbedding, chunkEmbedding);
|
|
33
|
+
return {
|
|
34
|
+
id: row.id,
|
|
35
|
+
sourceId: row.source_id,
|
|
36
|
+
filePath: row.file_path,
|
|
37
|
+
content: row.content,
|
|
38
|
+
startLine: row.start_line,
|
|
39
|
+
endLine: row.end_line,
|
|
40
|
+
tokens: row.tokens,
|
|
41
|
+
similarity,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
// Sort by similarity descending and take top N
|
|
45
|
+
scored.sort((a, b) => b.similarity - a.similarity);
|
|
46
|
+
return scored.slice(0, limit);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/selector/search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAsBpD,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAqB,EACrB,KAAa,EACb,UAAyB,EAAE;IAE3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC;IAE7C,kBAAkB;IAClB,MAAM,cAAc,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;IAE1C,kBAAkB;IAClB,IAAI,GAAG,GAAG;;;GAGT,CAAC;IAEF,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,GAAG,IAAI,wBAAwB,YAAY,GAAG,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,0DAA0D;IAC1D,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CASxC,CAAC;IAEH,sCAAsC;IACtC,MAAM,MAAM,GAAkB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7C,MAAM,cAAc,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,gBAAgB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QAEpE,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,QAAQ,EAAE,GAAG,CAAC,SAAS;YACvB,QAAQ,EAAE,GAAG,CAAC,SAAS;YACvB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,OAAO,EAAE,GAAG,CAAC,QAAQ;YACrB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,UAAU;SACX,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,+CAA+C;IAC/C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAEnD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC"}
|