ruvector 0.2.23 → 0.2.25
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/bin/cli.js +211 -63
- package/dist/analysis/complexity.d.ts +52 -0
- package/dist/analysis/complexity.d.ts.map +1 -0
- package/dist/analysis/complexity.js +146 -0
- package/dist/analysis/index.d.ts +15 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +38 -0
- package/dist/analysis/patterns.d.ts +71 -0
- package/dist/analysis/patterns.d.ts.map +1 -0
- package/dist/analysis/patterns.js +243 -0
- package/dist/analysis/security.d.ts +51 -0
- package/dist/analysis/security.d.ts.map +1 -0
- package/dist/analysis/security.js +139 -0
- package/dist/core/adaptive-embedder.d.ts +156 -0
- package/dist/core/adaptive-embedder.d.ts.map +1 -0
- package/dist/core/adaptive-embedder.js +838 -0
- package/dist/core/agentdb-fast.d.ts +149 -0
- package/dist/core/agentdb-fast.d.ts.map +1 -0
- package/dist/core/agentdb-fast.js +301 -0
- package/dist/core/ast-parser.d.ts +108 -0
- package/dist/core/ast-parser.d.ts.map +1 -0
- package/dist/core/ast-parser.js +602 -0
- package/dist/core/attention-fallbacks.d.ts +321 -0
- package/dist/core/attention-fallbacks.d.ts.map +1 -0
- package/dist/core/attention-fallbacks.js +552 -0
- package/dist/core/cluster-wrapper.d.ts +148 -0
- package/dist/core/cluster-wrapper.d.ts.map +1 -0
- package/dist/core/cluster-wrapper.js +271 -0
- package/dist/core/coverage-router.d.ts +88 -0
- package/dist/core/coverage-router.d.ts.map +1 -0
- package/dist/core/coverage-router.js +315 -0
- package/dist/core/diff-embeddings.d.ts +93 -0
- package/dist/core/diff-embeddings.d.ts.map +1 -0
- package/dist/core/diff-embeddings.js +334 -0
- package/dist/core/diskann-wrapper.d.ts +53 -0
- package/dist/core/diskann-wrapper.d.ts.map +1 -0
- package/dist/core/diskann-wrapper.js +105 -0
- package/dist/core/gnn-wrapper.d.ts +143 -0
- package/dist/core/gnn-wrapper.d.ts.map +1 -0
- package/dist/core/gnn-wrapper.js +213 -0
- package/dist/core/graph-algorithms.d.ts +83 -0
- package/dist/core/graph-algorithms.d.ts.map +1 -0
- package/dist/core/graph-algorithms.js +514 -0
- package/dist/core/graph-wrapper.d.ts +147 -0
- package/dist/core/graph-wrapper.d.ts.map +1 -0
- package/dist/core/graph-wrapper.js +299 -0
- package/dist/core/index.d.ts +50 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +92 -0
- package/dist/core/intelligence-engine.d.ts +258 -0
- package/dist/core/intelligence-engine.d.ts.map +1 -0
- package/dist/core/intelligence-engine.js +1030 -0
- package/dist/core/learning-engine.d.ts +160 -0
- package/dist/core/learning-engine.d.ts.map +1 -0
- package/dist/core/learning-engine.js +589 -0
- package/dist/core/neural-embeddings.d.ts +393 -0
- package/dist/core/neural-embeddings.d.ts.map +1 -0
- package/dist/core/neural-embeddings.js +1091 -0
- package/dist/core/neural-perf.d.ts +331 -0
- package/dist/core/neural-perf.d.ts.map +1 -0
- package/dist/core/neural-perf.js +704 -0
- package/dist/core/onnx/pkg/package.json +3 -0
- package/dist/core/onnx-embedder.d.ts +105 -0
- package/dist/core/onnx-embedder.d.ts.map +1 -0
- package/dist/core/onnx-embedder.js +410 -0
- package/dist/core/onnx-optimized.d.ts +109 -0
- package/dist/core/onnx-optimized.d.ts.map +1 -0
- package/dist/core/onnx-optimized.js +419 -0
- package/dist/core/parallel-intelligence.d.ts +109 -0
- package/dist/core/parallel-intelligence.d.ts.map +1 -0
- package/dist/core/parallel-intelligence.js +340 -0
- package/dist/core/parallel-workers.d.ts +177 -0
- package/dist/core/parallel-workers.d.ts.map +1 -0
- package/dist/core/parallel-workers.js +783 -0
- package/dist/core/router-wrapper.d.ts +75 -0
- package/dist/core/router-wrapper.d.ts.map +1 -0
- package/dist/core/router-wrapper.js +243 -0
- package/dist/core/rvf-wrapper.d.ts +86 -0
- package/dist/core/rvf-wrapper.d.ts.map +1 -0
- package/dist/core/rvf-wrapper.js +102 -0
- package/dist/core/sona-wrapper.d.ts +226 -0
- package/dist/core/sona-wrapper.d.ts.map +1 -0
- package/dist/core/sona-wrapper.js +282 -0
- package/dist/core/tensor-compress.d.ts +134 -0
- package/dist/core/tensor-compress.d.ts.map +1 -0
- package/dist/core/tensor-compress.js +432 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +258 -0
- package/dist/services/embedding-service.d.ts +136 -0
- package/dist/services/embedding-service.d.ts.map +1 -0
- package/dist/services/embedding-service.js +294 -0
- package/dist/services/index.d.ts +6 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +26 -0
- package/dist/types.d.ts +145 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/workers/benchmark.d.ts +44 -0
- package/dist/workers/benchmark.d.ts.map +1 -0
- package/dist/workers/benchmark.js +230 -0
- package/dist/workers/index.d.ts +10 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +25 -0
- package/dist/workers/native-worker.d.ts +76 -0
- package/dist/workers/native-worker.d.ts.map +1 -0
- package/dist/workers/native-worker.js +490 -0
- package/dist/workers/types.d.ts +69 -0
- package/dist/workers/types.d.ts.map +1 -0
- package/dist/workers/types.js +7 -0
- package/package.json +8 -7
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff Embeddings - Semantic encoding of git diffs
|
|
3
|
+
*
|
|
4
|
+
* Generates embeddings for code changes to enable:
|
|
5
|
+
* - Change classification (feature, bugfix, refactor)
|
|
6
|
+
* - Similar change detection
|
|
7
|
+
* - Risk assessment
|
|
8
|
+
* - Review prioritization
|
|
9
|
+
*/
|
|
10
|
+
export interface DiffHunk {
|
|
11
|
+
file: string;
|
|
12
|
+
oldStart: number;
|
|
13
|
+
oldLines: number;
|
|
14
|
+
newStart: number;
|
|
15
|
+
newLines: number;
|
|
16
|
+
content: string;
|
|
17
|
+
additions: string[];
|
|
18
|
+
deletions: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface DiffAnalysis {
|
|
21
|
+
file: string;
|
|
22
|
+
hunks: DiffHunk[];
|
|
23
|
+
totalAdditions: number;
|
|
24
|
+
totalDeletions: number;
|
|
25
|
+
complexity: number;
|
|
26
|
+
riskScore: number;
|
|
27
|
+
category: 'feature' | 'bugfix' | 'refactor' | 'docs' | 'test' | 'config' | 'unknown';
|
|
28
|
+
embedding?: number[];
|
|
29
|
+
}
|
|
30
|
+
export interface CommitAnalysis {
|
|
31
|
+
hash: string;
|
|
32
|
+
message: string;
|
|
33
|
+
author: string;
|
|
34
|
+
date: string;
|
|
35
|
+
files: DiffAnalysis[];
|
|
36
|
+
totalAdditions: number;
|
|
37
|
+
totalDeletions: number;
|
|
38
|
+
riskScore: number;
|
|
39
|
+
embedding?: number[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parse a unified diff into hunks
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseDiff(diff: string): DiffHunk[];
|
|
45
|
+
/**
|
|
46
|
+
* Classify a change based on patterns
|
|
47
|
+
*/
|
|
48
|
+
export declare function classifyChange(diff: string, message?: string): 'feature' | 'bugfix' | 'refactor' | 'docs' | 'test' | 'config' | 'unknown';
|
|
49
|
+
/**
|
|
50
|
+
* Calculate risk score for a diff
|
|
51
|
+
*/
|
|
52
|
+
export declare function calculateRiskScore(analysis: DiffAnalysis): number;
|
|
53
|
+
/**
|
|
54
|
+
* Analyze a single file diff
|
|
55
|
+
*/
|
|
56
|
+
export declare function analyzeFileDiff(file: string, diff: string, message?: string): Promise<DiffAnalysis>;
|
|
57
|
+
/**
|
|
58
|
+
* Get diff for a commit
|
|
59
|
+
*/
|
|
60
|
+
export declare function getCommitDiff(commitHash?: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Get diff for staged changes
|
|
63
|
+
*/
|
|
64
|
+
export declare function getStagedDiff(): string;
|
|
65
|
+
/**
|
|
66
|
+
* Get diff for unstaged changes
|
|
67
|
+
*/
|
|
68
|
+
export declare function getUnstagedDiff(): string;
|
|
69
|
+
/**
|
|
70
|
+
* Analyze a commit
|
|
71
|
+
*/
|
|
72
|
+
export declare function analyzeCommit(commitHash?: string): Promise<CommitAnalysis>;
|
|
73
|
+
/**
|
|
74
|
+
* Find similar past commits based on diff embeddings
|
|
75
|
+
*/
|
|
76
|
+
export declare function findSimilarCommits(currentDiff: string, recentCommits?: number, topK?: number): Promise<Array<{
|
|
77
|
+
hash: string;
|
|
78
|
+
similarity: number;
|
|
79
|
+
message: string;
|
|
80
|
+
}>>;
|
|
81
|
+
declare const _default: {
|
|
82
|
+
parseDiff: typeof parseDiff;
|
|
83
|
+
classifyChange: typeof classifyChange;
|
|
84
|
+
calculateRiskScore: typeof calculateRiskScore;
|
|
85
|
+
analyzeFileDiff: typeof analyzeFileDiff;
|
|
86
|
+
analyzeCommit: typeof analyzeCommit;
|
|
87
|
+
getCommitDiff: typeof getCommitDiff;
|
|
88
|
+
getStagedDiff: typeof getStagedDiff;
|
|
89
|
+
getUnstagedDiff: typeof getUnstagedDiff;
|
|
90
|
+
findSimilarCommits: typeof findSimilarCommits;
|
|
91
|
+
};
|
|
92
|
+
export default _default;
|
|
93
|
+
//# sourceMappingURL=diff-embeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-embeddings.d.ts","sourceRoot":"","sources":["../../src/core/diff-embeddings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IACrF,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAsDlD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAsB7I;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CA2BjE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAsC7G;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,GAAE,MAAe,GAAG,MAAM,CASjE;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAStC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CASxC;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,UAAU,GAAE,MAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAwDxF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,aAAa,GAAE,MAAW,EAC1B,IAAI,GAAE,MAAU,GACf,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAgCvE;;;;;;;;;;;;AAmBD,wBAUE"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Diff Embeddings - Semantic encoding of git diffs
|
|
4
|
+
*
|
|
5
|
+
* Generates embeddings for code changes to enable:
|
|
6
|
+
* - Change classification (feature, bugfix, refactor)
|
|
7
|
+
* - Similar change detection
|
|
8
|
+
* - Risk assessment
|
|
9
|
+
* - Review prioritization
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.parseDiff = parseDiff;
|
|
13
|
+
exports.classifyChange = classifyChange;
|
|
14
|
+
exports.calculateRiskScore = calculateRiskScore;
|
|
15
|
+
exports.analyzeFileDiff = analyzeFileDiff;
|
|
16
|
+
exports.getCommitDiff = getCommitDiff;
|
|
17
|
+
exports.getStagedDiff = getStagedDiff;
|
|
18
|
+
exports.getUnstagedDiff = getUnstagedDiff;
|
|
19
|
+
exports.analyzeCommit = analyzeCommit;
|
|
20
|
+
exports.findSimilarCommits = findSimilarCommits;
|
|
21
|
+
const child_process_1 = require("child_process");
|
|
22
|
+
const onnx_embedder_1 = require("./onnx-embedder");
|
|
23
|
+
/**
|
|
24
|
+
* Parse a unified diff into hunks
|
|
25
|
+
*/
|
|
26
|
+
function parseDiff(diff) {
|
|
27
|
+
const hunks = [];
|
|
28
|
+
const lines = diff.split('\n');
|
|
29
|
+
let currentFile = '';
|
|
30
|
+
let currentHunk = null;
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
// File header
|
|
33
|
+
if (line.startsWith('diff --git')) {
|
|
34
|
+
const match = line.match(/diff --git a\/(.+) b\/(.+)/);
|
|
35
|
+
if (match) {
|
|
36
|
+
currentFile = match[2];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Hunk header
|
|
40
|
+
if (line.startsWith('@@')) {
|
|
41
|
+
if (currentHunk) {
|
|
42
|
+
hunks.push(currentHunk);
|
|
43
|
+
}
|
|
44
|
+
const match = line.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);
|
|
45
|
+
if (match) {
|
|
46
|
+
currentHunk = {
|
|
47
|
+
file: currentFile,
|
|
48
|
+
oldStart: parseInt(match[1]),
|
|
49
|
+
oldLines: parseInt(match[2] || '1'),
|
|
50
|
+
newStart: parseInt(match[3]),
|
|
51
|
+
newLines: parseInt(match[4] || '1'),
|
|
52
|
+
content: '',
|
|
53
|
+
additions: [],
|
|
54
|
+
deletions: [],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (currentHunk) {
|
|
59
|
+
// Content lines
|
|
60
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
61
|
+
currentHunk.additions.push(line.substring(1));
|
|
62
|
+
currentHunk.content += line + '\n';
|
|
63
|
+
}
|
|
64
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
65
|
+
currentHunk.deletions.push(line.substring(1));
|
|
66
|
+
currentHunk.content += line + '\n';
|
|
67
|
+
}
|
|
68
|
+
else if (line.startsWith(' ')) {
|
|
69
|
+
currentHunk.content += line + '\n';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (currentHunk) {
|
|
74
|
+
hunks.push(currentHunk);
|
|
75
|
+
}
|
|
76
|
+
return hunks;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Classify a change based on patterns
|
|
80
|
+
*/
|
|
81
|
+
function classifyChange(diff, message = '') {
|
|
82
|
+
const lowerMessage = message.toLowerCase();
|
|
83
|
+
const lowerDiff = diff.toLowerCase();
|
|
84
|
+
// Check message patterns
|
|
85
|
+
if (/\b(fix|bug|issue|error|crash|patch)\b/.test(lowerMessage))
|
|
86
|
+
return 'bugfix';
|
|
87
|
+
if (/\b(feat|feature|add|new|implement)\b/.test(lowerMessage))
|
|
88
|
+
return 'feature';
|
|
89
|
+
if (/\b(refactor|clean|improve|optimize)\b/.test(lowerMessage))
|
|
90
|
+
return 'refactor';
|
|
91
|
+
if (/\b(doc|readme|comment|jsdoc)\b/.test(lowerMessage))
|
|
92
|
+
return 'docs';
|
|
93
|
+
if (/\b(test|spec|coverage)\b/.test(lowerMessage))
|
|
94
|
+
return 'test';
|
|
95
|
+
if (/\b(config|ci|cd|build|deps)\b/.test(lowerMessage))
|
|
96
|
+
return 'config';
|
|
97
|
+
// Check diff patterns
|
|
98
|
+
if (/\.(md|txt|rst)$/.test(diff))
|
|
99
|
+
return 'docs';
|
|
100
|
+
if (/\.(test|spec)\.[jt]sx?/.test(diff))
|
|
101
|
+
return 'test';
|
|
102
|
+
if (/\.(json|ya?ml|toml|ini)$/.test(diff))
|
|
103
|
+
return 'config';
|
|
104
|
+
// Check content patterns
|
|
105
|
+
if (/\bcatch\b|\btry\b|\berror\b/.test(lowerDiff) && /\bfix\b/.test(lowerDiff))
|
|
106
|
+
return 'bugfix';
|
|
107
|
+
if (/\bfunction\b|\bclass\b|\bexport\b/.test(lowerDiff))
|
|
108
|
+
return 'feature';
|
|
109
|
+
return 'unknown';
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Calculate risk score for a diff
|
|
113
|
+
*/
|
|
114
|
+
function calculateRiskScore(analysis) {
|
|
115
|
+
let risk = 0;
|
|
116
|
+
// Size risk
|
|
117
|
+
const totalChanges = analysis.totalAdditions + analysis.totalDeletions;
|
|
118
|
+
if (totalChanges > 500)
|
|
119
|
+
risk += 0.3;
|
|
120
|
+
else if (totalChanges > 200)
|
|
121
|
+
risk += 0.2;
|
|
122
|
+
else if (totalChanges > 50)
|
|
123
|
+
risk += 0.1;
|
|
124
|
+
// Complexity risk
|
|
125
|
+
if (analysis.complexity > 20)
|
|
126
|
+
risk += 0.2;
|
|
127
|
+
else if (analysis.complexity > 10)
|
|
128
|
+
risk += 0.1;
|
|
129
|
+
// File type risk
|
|
130
|
+
if (analysis.file.includes('auth') || analysis.file.includes('security'))
|
|
131
|
+
risk += 0.2;
|
|
132
|
+
if (analysis.file.includes('database') || analysis.file.includes('migration'))
|
|
133
|
+
risk += 0.15;
|
|
134
|
+
if (analysis.file.includes('api') || analysis.file.includes('endpoint'))
|
|
135
|
+
risk += 0.1;
|
|
136
|
+
// Pattern risk (deletions of error handling, etc.)
|
|
137
|
+
for (const hunk of analysis.hunks) {
|
|
138
|
+
for (const del of hunk.deletions) {
|
|
139
|
+
if (/\bcatch\b|\berror\b|\bvalidat/.test(del))
|
|
140
|
+
risk += 0.1;
|
|
141
|
+
if (/\bif\b.*\bnull\b|\bundefined\b/.test(del))
|
|
142
|
+
risk += 0.05;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return Math.min(1, risk);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Analyze a single file diff
|
|
149
|
+
*/
|
|
150
|
+
async function analyzeFileDiff(file, diff, message = '') {
|
|
151
|
+
const hunks = parseDiff(diff).filter(h => h.file === file || h.file === '');
|
|
152
|
+
const totalAdditions = hunks.reduce((sum, h) => sum + h.additions.length, 0);
|
|
153
|
+
const totalDeletions = hunks.reduce((sum, h) => sum + h.deletions.length, 0);
|
|
154
|
+
// Calculate complexity (branch keywords in additions)
|
|
155
|
+
let complexity = 0;
|
|
156
|
+
for (const hunk of hunks) {
|
|
157
|
+
for (const add of hunk.additions) {
|
|
158
|
+
if (/\bif\b|\belse\b|\bfor\b|\bwhile\b|\bswitch\b|\bcatch\b|\?/.test(add)) {
|
|
159
|
+
complexity++;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const category = classifyChange(diff, message);
|
|
164
|
+
const analysis = {
|
|
165
|
+
file,
|
|
166
|
+
hunks,
|
|
167
|
+
totalAdditions,
|
|
168
|
+
totalDeletions,
|
|
169
|
+
complexity,
|
|
170
|
+
riskScore: 0,
|
|
171
|
+
category,
|
|
172
|
+
};
|
|
173
|
+
analysis.riskScore = calculateRiskScore(analysis);
|
|
174
|
+
// Generate embedding for the diff
|
|
175
|
+
if ((0, onnx_embedder_1.isReady)()) {
|
|
176
|
+
const diffText = hunks.map(h => h.content).join('\n');
|
|
177
|
+
const result = await (0, onnx_embedder_1.embed)(`${category} change in ${file}: ${diffText.substring(0, 500)}`);
|
|
178
|
+
analysis.embedding = result.embedding;
|
|
179
|
+
}
|
|
180
|
+
return analysis;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get diff for a commit
|
|
184
|
+
*/
|
|
185
|
+
function getCommitDiff(commitHash = 'HEAD') {
|
|
186
|
+
try {
|
|
187
|
+
return (0, child_process_1.execSync)(`git show ${commitHash} --format="" 2>/dev/null`, {
|
|
188
|
+
encoding: 'utf8',
|
|
189
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return '';
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get diff for staged changes
|
|
198
|
+
*/
|
|
199
|
+
function getStagedDiff() {
|
|
200
|
+
try {
|
|
201
|
+
return (0, child_process_1.execSync)('git diff --cached 2>/dev/null', {
|
|
202
|
+
encoding: 'utf8',
|
|
203
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return '';
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get diff for unstaged changes
|
|
212
|
+
*/
|
|
213
|
+
function getUnstagedDiff() {
|
|
214
|
+
try {
|
|
215
|
+
return (0, child_process_1.execSync)('git diff 2>/dev/null', {
|
|
216
|
+
encoding: 'utf8',
|
|
217
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return '';
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Analyze a commit
|
|
226
|
+
*/
|
|
227
|
+
async function analyzeCommit(commitHash = 'HEAD') {
|
|
228
|
+
const diff = getCommitDiff(commitHash);
|
|
229
|
+
// Get commit metadata
|
|
230
|
+
let message = '', author = '', date = '';
|
|
231
|
+
try {
|
|
232
|
+
const info = (0, child_process_1.execSync)(`git log -1 --format="%s|%an|%aI" ${commitHash} 2>/dev/null`, {
|
|
233
|
+
encoding: 'utf8',
|
|
234
|
+
}).trim();
|
|
235
|
+
[message, author, date] = info.split('|');
|
|
236
|
+
}
|
|
237
|
+
catch { }
|
|
238
|
+
// Parse hunks and group by file
|
|
239
|
+
const hunks = parseDiff(diff);
|
|
240
|
+
const fileHunks = new Map();
|
|
241
|
+
for (const hunk of hunks) {
|
|
242
|
+
if (!fileHunks.has(hunk.file)) {
|
|
243
|
+
fileHunks.set(hunk.file, []);
|
|
244
|
+
}
|
|
245
|
+
fileHunks.get(hunk.file).push(hunk);
|
|
246
|
+
}
|
|
247
|
+
// Analyze each file
|
|
248
|
+
const files = [];
|
|
249
|
+
for (const [file, fileHunkList] of fileHunks) {
|
|
250
|
+
const fileDiff = fileHunkList.map(h => h.content).join('\n');
|
|
251
|
+
const analysis = await analyzeFileDiff(file, diff, message);
|
|
252
|
+
files.push(analysis);
|
|
253
|
+
}
|
|
254
|
+
const totalAdditions = files.reduce((sum, f) => sum + f.totalAdditions, 0);
|
|
255
|
+
const totalDeletions = files.reduce((sum, f) => sum + f.totalDeletions, 0);
|
|
256
|
+
const riskScore = files.length > 0
|
|
257
|
+
? files.reduce((sum, f) => sum + f.riskScore, 0) / files.length
|
|
258
|
+
: 0;
|
|
259
|
+
// Generate commit embedding
|
|
260
|
+
let embedding;
|
|
261
|
+
if ((0, onnx_embedder_1.isReady)()) {
|
|
262
|
+
const commitText = `${message}\n\nFiles changed: ${files.map(f => f.file).join(', ')}\n+${totalAdditions} -${totalDeletions}`;
|
|
263
|
+
const result = await (0, onnx_embedder_1.embed)(commitText);
|
|
264
|
+
embedding = result.embedding;
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
hash: commitHash,
|
|
268
|
+
message,
|
|
269
|
+
author,
|
|
270
|
+
date,
|
|
271
|
+
files,
|
|
272
|
+
totalAdditions,
|
|
273
|
+
totalDeletions,
|
|
274
|
+
riskScore,
|
|
275
|
+
embedding,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Find similar past commits based on diff embeddings
|
|
280
|
+
*/
|
|
281
|
+
async function findSimilarCommits(currentDiff, recentCommits = 50, topK = 5) {
|
|
282
|
+
if (!(0, onnx_embedder_1.isReady)()) {
|
|
283
|
+
await (0, onnx_embedder_1.initOnnxEmbedder)();
|
|
284
|
+
}
|
|
285
|
+
// Get current diff embedding
|
|
286
|
+
const currentEmbedding = (await (0, onnx_embedder_1.embed)(currentDiff.substring(0, 1000))).embedding;
|
|
287
|
+
// Get recent commits
|
|
288
|
+
let commits = [];
|
|
289
|
+
try {
|
|
290
|
+
commits = (0, child_process_1.execSync)(`git log -${recentCommits} --format="%H" 2>/dev/null`, {
|
|
291
|
+
encoding: 'utf8',
|
|
292
|
+
}).trim().split('\n');
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
return [];
|
|
296
|
+
}
|
|
297
|
+
// Analyze and compare
|
|
298
|
+
const results = [];
|
|
299
|
+
for (const hash of commits.slice(0, Math.min(commits.length, recentCommits))) {
|
|
300
|
+
const analysis = await analyzeCommit(hash);
|
|
301
|
+
if (analysis.embedding) {
|
|
302
|
+
const similarity = cosineSimilarity(currentEmbedding, analysis.embedding);
|
|
303
|
+
results.push({ hash, similarity, message: analysis.message });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return results
|
|
307
|
+
.sort((a, b) => b.similarity - a.similarity)
|
|
308
|
+
.slice(0, topK);
|
|
309
|
+
}
|
|
310
|
+
function cosineSimilarity(a, b) {
|
|
311
|
+
if (a.length !== b.length)
|
|
312
|
+
return 0;
|
|
313
|
+
let dotProduct = 0;
|
|
314
|
+
let normA = 0;
|
|
315
|
+
let normB = 0;
|
|
316
|
+
for (let i = 0; i < a.length; i++) {
|
|
317
|
+
dotProduct += a[i] * b[i];
|
|
318
|
+
normA += a[i] * a[i];
|
|
319
|
+
normB += b[i] * b[i];
|
|
320
|
+
}
|
|
321
|
+
const magnitude = Math.sqrt(normA) * Math.sqrt(normB);
|
|
322
|
+
return magnitude === 0 ? 0 : dotProduct / magnitude;
|
|
323
|
+
}
|
|
324
|
+
exports.default = {
|
|
325
|
+
parseDiff,
|
|
326
|
+
classifyChange,
|
|
327
|
+
calculateRiskScore,
|
|
328
|
+
analyzeFileDiff,
|
|
329
|
+
analyzeCommit,
|
|
330
|
+
getCommitDiff,
|
|
331
|
+
getStagedDiff,
|
|
332
|
+
getUnstagedDiff,
|
|
333
|
+
findSimilarCommits,
|
|
334
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiskANN Wrapper — Vamana graph ANN for billion-scale vector search
|
|
3
|
+
*
|
|
4
|
+
* Wraps @ruvector/diskann for SSD-friendly approximate nearest neighbor search.
|
|
5
|
+
* Provides the same lazy-load pattern as other native wrappers.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isDiskAnnAvailable(): boolean;
|
|
8
|
+
export interface DiskAnnConfig {
|
|
9
|
+
dim: number;
|
|
10
|
+
maxDegree?: number;
|
|
11
|
+
buildBeam?: number;
|
|
12
|
+
searchBeam?: number;
|
|
13
|
+
alpha?: number;
|
|
14
|
+
pqSubspaces?: number;
|
|
15
|
+
pqIterations?: number;
|
|
16
|
+
storagePath?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface DiskAnnSearchResult {
|
|
19
|
+
id: string;
|
|
20
|
+
distance: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* DiskANN index for large-scale approximate nearest neighbor search.
|
|
24
|
+
*
|
|
25
|
+
* Uses the Vamana graph algorithm with optional Product Quantization.
|
|
26
|
+
* Build after all inserts, then search.
|
|
27
|
+
*/
|
|
28
|
+
export declare class DiskAnnIndex {
|
|
29
|
+
private inner;
|
|
30
|
+
constructor(config: DiskAnnConfig);
|
|
31
|
+
/** Insert a vector with a string ID */
|
|
32
|
+
insert(id: string, vector: Float32Array | number[]): void;
|
|
33
|
+
/** Insert a batch of vectors (flat Float32Array: N * dim) */
|
|
34
|
+
insertBatch(ids: string[], vectors: Float32Array, dim: number): void;
|
|
35
|
+
/** Build the Vamana graph index (required before search) */
|
|
36
|
+
build(): void;
|
|
37
|
+
/** Build index asynchronously */
|
|
38
|
+
buildAsync(): Promise<void>;
|
|
39
|
+
/** Search for k nearest neighbors */
|
|
40
|
+
search(query: Float32Array | number[], k?: number): DiskAnnSearchResult[];
|
|
41
|
+
/** Search asynchronously */
|
|
42
|
+
searchAsync(query: Float32Array | number[], k?: number): Promise<DiskAnnSearchResult[]>;
|
|
43
|
+
/** Delete a vector by ID */
|
|
44
|
+
delete(id: string): boolean;
|
|
45
|
+
/** Get the number of vectors */
|
|
46
|
+
count(): number;
|
|
47
|
+
/** Save index to directory */
|
|
48
|
+
save(dir: string): void;
|
|
49
|
+
/** Load index from directory */
|
|
50
|
+
static load(dir: string): DiskAnnIndex;
|
|
51
|
+
}
|
|
52
|
+
export default DiskAnnIndex;
|
|
53
|
+
//# sourceMappingURL=diskann-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diskann-wrapper.d.ts","sourceRoot":"","sources":["../../src/core/diskann-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH,wBAAgB,kBAAkB,IAAI,OAAO,CAO5C;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAM;gBAEP,MAAM,EAAE,aAAa;IAcjC,uCAAuC;IACvC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE,GAAG,IAAI;IAKzD,6DAA6D;IAC7D,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAIpE,4DAA4D;IAC5D,KAAK,IAAI,IAAI;IAIb,iCAAiC;IAC3B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,qCAAqC;IACrC,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,EAAE,CAAC,GAAE,MAAW,GAAG,mBAAmB,EAAE;IAK7E,4BAA4B;IACtB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,EAAE,CAAC,GAAE,MAAW,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAKjG,4BAA4B;IAC5B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI3B,gCAAgC;IAChC,KAAK,IAAI,MAAM;IAIf,8BAA8B;IAC9B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIvB,gCAAgC;IAChC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY;CAMvC;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DiskANN Wrapper — Vamana graph ANN for billion-scale vector search
|
|
4
|
+
*
|
|
5
|
+
* Wraps @ruvector/diskann for SSD-friendly approximate nearest neighbor search.
|
|
6
|
+
* Provides the same lazy-load pattern as other native wrappers.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.DiskAnnIndex = void 0;
|
|
10
|
+
exports.isDiskAnnAvailable = isDiskAnnAvailable;
|
|
11
|
+
let diskannModule = null;
|
|
12
|
+
let loadError = null;
|
|
13
|
+
function getDiskAnnModule() {
|
|
14
|
+
if (diskannModule)
|
|
15
|
+
return diskannModule;
|
|
16
|
+
if (loadError)
|
|
17
|
+
throw loadError;
|
|
18
|
+
try {
|
|
19
|
+
diskannModule = require('@ruvector/diskann');
|
|
20
|
+
return diskannModule;
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
loadError = new Error(`@ruvector/diskann not installed: ${e.message}\n` +
|
|
24
|
+
`Install with: npm install @ruvector/diskann`);
|
|
25
|
+
throw loadError;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function isDiskAnnAvailable() {
|
|
29
|
+
try {
|
|
30
|
+
getDiskAnnModule();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* DiskANN index for large-scale approximate nearest neighbor search.
|
|
39
|
+
*
|
|
40
|
+
* Uses the Vamana graph algorithm with optional Product Quantization.
|
|
41
|
+
* Build after all inserts, then search.
|
|
42
|
+
*/
|
|
43
|
+
class DiskAnnIndex {
|
|
44
|
+
constructor(config) {
|
|
45
|
+
const mod = getDiskAnnModule();
|
|
46
|
+
this.inner = new mod.DiskAnn({
|
|
47
|
+
dim: config.dim,
|
|
48
|
+
maxDegree: config.maxDegree ?? 64,
|
|
49
|
+
buildBeam: config.buildBeam ?? 128,
|
|
50
|
+
searchBeam: config.searchBeam ?? 64,
|
|
51
|
+
alpha: config.alpha ?? 1.2,
|
|
52
|
+
pqSubspaces: config.pqSubspaces ?? 0,
|
|
53
|
+
pqIterations: config.pqIterations ?? 10,
|
|
54
|
+
storagePath: config.storagePath,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Insert a vector with a string ID */
|
|
58
|
+
insert(id, vector) {
|
|
59
|
+
const v = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
|
60
|
+
this.inner.insert(id, v);
|
|
61
|
+
}
|
|
62
|
+
/** Insert a batch of vectors (flat Float32Array: N * dim) */
|
|
63
|
+
insertBatch(ids, vectors, dim) {
|
|
64
|
+
this.inner.insertBatch(ids, vectors, dim);
|
|
65
|
+
}
|
|
66
|
+
/** Build the Vamana graph index (required before search) */
|
|
67
|
+
build() {
|
|
68
|
+
this.inner.build();
|
|
69
|
+
}
|
|
70
|
+
/** Build index asynchronously */
|
|
71
|
+
async buildAsync() {
|
|
72
|
+
return this.inner.buildAsync();
|
|
73
|
+
}
|
|
74
|
+
/** Search for k nearest neighbors */
|
|
75
|
+
search(query, k = 10) {
|
|
76
|
+
const q = query instanceof Float32Array ? query : new Float32Array(query);
|
|
77
|
+
return this.inner.search(q, k);
|
|
78
|
+
}
|
|
79
|
+
/** Search asynchronously */
|
|
80
|
+
async searchAsync(query, k = 10) {
|
|
81
|
+
const q = query instanceof Float32Array ? query : new Float32Array(query);
|
|
82
|
+
return this.inner.searchAsync(q, k);
|
|
83
|
+
}
|
|
84
|
+
/** Delete a vector by ID */
|
|
85
|
+
delete(id) {
|
|
86
|
+
return this.inner.delete(id);
|
|
87
|
+
}
|
|
88
|
+
/** Get the number of vectors */
|
|
89
|
+
count() {
|
|
90
|
+
return this.inner.count();
|
|
91
|
+
}
|
|
92
|
+
/** Save index to directory */
|
|
93
|
+
save(dir) {
|
|
94
|
+
this.inner.save(dir);
|
|
95
|
+
}
|
|
96
|
+
/** Load index from directory */
|
|
97
|
+
static load(dir) {
|
|
98
|
+
const mod = getDiskAnnModule();
|
|
99
|
+
const instance = new DiskAnnIndex({ dim: 1 }); // placeholder
|
|
100
|
+
instance.inner = mod.DiskAnn.load(dir);
|
|
101
|
+
return instance;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.DiskAnnIndex = DiskAnnIndex;
|
|
105
|
+
exports.default = DiskAnnIndex;
|