@renseiai/agentfactory-code-intelligence 0.8.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/LICENSE +21 -0
- package/dist/src/__tests__/types.test.d.ts +2 -0
- package/dist/src/__tests__/types.test.d.ts.map +1 -0
- package/dist/src/__tests__/types.test.js +187 -0
- package/dist/src/index.d.ts +26 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +29 -0
- package/dist/src/indexing/__tests__/indexing.test.d.ts +2 -0
- package/dist/src/indexing/__tests__/indexing.test.d.ts.map +1 -0
- package/dist/src/indexing/__tests__/indexing.test.js +193 -0
- package/dist/src/indexing/change-detector.d.ts +16 -0
- package/dist/src/indexing/change-detector.d.ts.map +1 -0
- package/dist/src/indexing/change-detector.js +38 -0
- package/dist/src/indexing/git-hash-provider.d.ts +11 -0
- package/dist/src/indexing/git-hash-provider.d.ts.map +1 -0
- package/dist/src/indexing/git-hash-provider.js +25 -0
- package/dist/src/indexing/incremental-indexer.d.ts +38 -0
- package/dist/src/indexing/incremental-indexer.d.ts.map +1 -0
- package/dist/src/indexing/incremental-indexer.js +122 -0
- package/dist/src/indexing/merkle-tree.d.ts +33 -0
- package/dist/src/indexing/merkle-tree.d.ts.map +1 -0
- package/dist/src/indexing/merkle-tree.js +107 -0
- package/dist/src/memory/__tests__/dedup.test.d.ts +2 -0
- package/dist/src/memory/__tests__/dedup.test.d.ts.map +1 -0
- package/dist/src/memory/__tests__/dedup.test.js +173 -0
- package/dist/src/memory/dedup-pipeline.d.ts +24 -0
- package/dist/src/memory/dedup-pipeline.d.ts.map +1 -0
- package/dist/src/memory/dedup-pipeline.js +73 -0
- package/dist/src/memory/memory-store.d.ts +22 -0
- package/dist/src/memory/memory-store.d.ts.map +1 -0
- package/dist/src/memory/memory-store.js +32 -0
- package/dist/src/memory/simhash.d.ts +16 -0
- package/dist/src/memory/simhash.d.ts.map +1 -0
- package/dist/src/memory/simhash.js +67 -0
- package/dist/src/memory/xxhash.d.ts +3 -0
- package/dist/src/memory/xxhash.d.ts.map +1 -0
- package/dist/src/memory/xxhash.js +13 -0
- package/dist/src/parser/__tests__/multi-language.test.d.ts +2 -0
- package/dist/src/parser/__tests__/multi-language.test.d.ts.map +1 -0
- package/dist/src/parser/__tests__/multi-language.test.js +350 -0
- package/dist/src/parser/__tests__/symbol-extractor.test.d.ts +2 -0
- package/dist/src/parser/__tests__/symbol-extractor.test.d.ts.map +1 -0
- package/dist/src/parser/__tests__/symbol-extractor.test.js +188 -0
- package/dist/src/parser/go-extractor.d.ts +8 -0
- package/dist/src/parser/go-extractor.d.ts.map +1 -0
- package/dist/src/parser/go-extractor.js +127 -0
- package/dist/src/parser/python-extractor.d.ts +8 -0
- package/dist/src/parser/python-extractor.d.ts.map +1 -0
- package/dist/src/parser/python-extractor.js +92 -0
- package/dist/src/parser/rust-extractor.d.ts +8 -0
- package/dist/src/parser/rust-extractor.d.ts.map +1 -0
- package/dist/src/parser/rust-extractor.js +168 -0
- package/dist/src/parser/symbol-extractor.d.ts +14 -0
- package/dist/src/parser/symbol-extractor.d.ts.map +1 -0
- package/dist/src/parser/symbol-extractor.js +47 -0
- package/dist/src/parser/typescript-extractor.d.ts +13 -0
- package/dist/src/parser/typescript-extractor.d.ts.map +1 -0
- package/dist/src/parser/typescript-extractor.js +229 -0
- package/dist/src/plugin/__tests__/plugin.test.d.ts +2 -0
- package/dist/src/plugin/__tests__/plugin.test.d.ts.map +1 -0
- package/dist/src/plugin/__tests__/plugin.test.js +48 -0
- package/dist/src/plugin/code-intelligence-plugin.d.ts +15 -0
- package/dist/src/plugin/code-intelligence-plugin.d.ts.map +1 -0
- package/dist/src/plugin/code-intelligence-plugin.js +102 -0
- package/dist/src/repo-map/__tests__/repo-map.test.d.ts +2 -0
- package/dist/src/repo-map/__tests__/repo-map.test.d.ts.map +1 -0
- package/dist/src/repo-map/__tests__/repo-map.test.js +186 -0
- package/dist/src/repo-map/dependency-graph.d.ts +30 -0
- package/dist/src/repo-map/dependency-graph.d.ts.map +1 -0
- package/dist/src/repo-map/dependency-graph.js +105 -0
- package/dist/src/repo-map/pagerank.d.ts +20 -0
- package/dist/src/repo-map/pagerank.d.ts.map +1 -0
- package/dist/src/repo-map/pagerank.js +68 -0
- package/dist/src/repo-map/repo-map-generator.d.ts +20 -0
- package/dist/src/repo-map/repo-map-generator.d.ts.map +1 -0
- package/dist/src/repo-map/repo-map-generator.js +66 -0
- package/dist/src/search/__tests__/search.test.d.ts +2 -0
- package/dist/src/search/__tests__/search.test.d.ts.map +1 -0
- package/dist/src/search/__tests__/search.test.js +191 -0
- package/dist/src/search/bm25.d.ts +24 -0
- package/dist/src/search/bm25.d.ts.map +1 -0
- package/dist/src/search/bm25.js +44 -0
- package/dist/src/search/inverted-index.d.ts +31 -0
- package/dist/src/search/inverted-index.d.ts.map +1 -0
- package/dist/src/search/inverted-index.js +72 -0
- package/dist/src/search/search-engine.d.ts +22 -0
- package/dist/src/search/search-engine.d.ts.map +1 -0
- package/dist/src/search/search-engine.js +76 -0
- package/dist/src/search/tokenizer.d.ts +11 -0
- package/dist/src/search/tokenizer.d.ts.map +1 -0
- package/dist/src/search/tokenizer.js +48 -0
- package/dist/src/types.d.ts +242 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +96 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Rensei AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/types.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { SymbolKindSchema, CodeSymbolSchema, FileASTSchema, FileIndexSchema, SearchQuerySchema, SearchResultSchema, MemoryEntrySchema, DedupResultSchema, IndexMetadataSchema, RepoMapEntrySchema, } from '../types.js';
|
|
3
|
+
describe('SymbolKindSchema', () => {
|
|
4
|
+
it('accepts valid symbol kinds', () => {
|
|
5
|
+
const kinds = ['function', 'class', 'interface', 'type', 'variable', 'method',
|
|
6
|
+
'property', 'import', 'export', 'enum', 'struct', 'trait', 'impl', 'macro',
|
|
7
|
+
'decorator', 'module'];
|
|
8
|
+
for (const kind of kinds) {
|
|
9
|
+
expect(SymbolKindSchema.parse(kind)).toBe(kind);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
it('rejects invalid symbol kinds', () => {
|
|
13
|
+
expect(() => SymbolKindSchema.parse('invalid')).toThrow();
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
describe('CodeSymbolSchema', () => {
|
|
17
|
+
it('parses a valid symbol', () => {
|
|
18
|
+
const symbol = CodeSymbolSchema.parse({
|
|
19
|
+
name: 'myFunction',
|
|
20
|
+
kind: 'function',
|
|
21
|
+
filePath: 'src/utils.ts',
|
|
22
|
+
line: 10,
|
|
23
|
+
exported: true,
|
|
24
|
+
signature: 'function myFunction(x: number): string',
|
|
25
|
+
});
|
|
26
|
+
expect(symbol.name).toBe('myFunction');
|
|
27
|
+
expect(symbol.kind).toBe('function');
|
|
28
|
+
expect(symbol.exported).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
it('applies defaults', () => {
|
|
31
|
+
const symbol = CodeSymbolSchema.parse({
|
|
32
|
+
name: 'x',
|
|
33
|
+
kind: 'variable',
|
|
34
|
+
filePath: 'a.ts',
|
|
35
|
+
line: 0,
|
|
36
|
+
});
|
|
37
|
+
expect(symbol.exported).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it('rejects empty name', () => {
|
|
40
|
+
expect(() => CodeSymbolSchema.parse({
|
|
41
|
+
name: '',
|
|
42
|
+
kind: 'function',
|
|
43
|
+
filePath: 'a.ts',
|
|
44
|
+
line: 0,
|
|
45
|
+
})).toThrow();
|
|
46
|
+
});
|
|
47
|
+
it('rejects negative line number', () => {
|
|
48
|
+
expect(() => CodeSymbolSchema.parse({
|
|
49
|
+
name: 'x',
|
|
50
|
+
kind: 'function',
|
|
51
|
+
filePath: 'a.ts',
|
|
52
|
+
line: -1,
|
|
53
|
+
})).toThrow();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('FileASTSchema', () => {
|
|
57
|
+
it('parses valid file AST', () => {
|
|
58
|
+
const ast = FileASTSchema.parse({
|
|
59
|
+
filePath: 'src/main.ts',
|
|
60
|
+
language: 'typescript',
|
|
61
|
+
symbols: [{
|
|
62
|
+
name: 'main',
|
|
63
|
+
kind: 'function',
|
|
64
|
+
filePath: 'src/main.ts',
|
|
65
|
+
line: 1,
|
|
66
|
+
}],
|
|
67
|
+
imports: ['./utils'],
|
|
68
|
+
exports: ['main'],
|
|
69
|
+
});
|
|
70
|
+
expect(ast.symbols).toHaveLength(1);
|
|
71
|
+
expect(ast.imports).toEqual(['./utils']);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('FileIndexSchema', () => {
|
|
75
|
+
it('parses valid file index', () => {
|
|
76
|
+
const idx = FileIndexSchema.parse({
|
|
77
|
+
filePath: 'src/lib.ts',
|
|
78
|
+
gitHash: 'abc123def456',
|
|
79
|
+
symbols: [],
|
|
80
|
+
lastIndexed: Date.now(),
|
|
81
|
+
});
|
|
82
|
+
expect(idx.gitHash).toBe('abc123def456');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('SearchQuerySchema', () => {
|
|
86
|
+
it('parses minimal query', () => {
|
|
87
|
+
const q = SearchQuerySchema.parse({ query: 'myFunc' });
|
|
88
|
+
expect(q.query).toBe('myFunc');
|
|
89
|
+
expect(q.maxResults).toBe(20);
|
|
90
|
+
});
|
|
91
|
+
it('parses full query', () => {
|
|
92
|
+
const q = SearchQuerySchema.parse({
|
|
93
|
+
query: 'handler',
|
|
94
|
+
maxResults: 10,
|
|
95
|
+
filePattern: '*.ts',
|
|
96
|
+
symbolKinds: ['function', 'method'],
|
|
97
|
+
language: 'typescript',
|
|
98
|
+
});
|
|
99
|
+
expect(q.symbolKinds).toEqual(['function', 'method']);
|
|
100
|
+
});
|
|
101
|
+
it('rejects empty query', () => {
|
|
102
|
+
expect(() => SearchQuerySchema.parse({ query: '' })).toThrow();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('SearchResultSchema', () => {
|
|
106
|
+
it('parses valid result', () => {
|
|
107
|
+
const result = SearchResultSchema.parse({
|
|
108
|
+
symbol: {
|
|
109
|
+
name: 'foo',
|
|
110
|
+
kind: 'function',
|
|
111
|
+
filePath: 'a.ts',
|
|
112
|
+
line: 5,
|
|
113
|
+
},
|
|
114
|
+
score: 1.5,
|
|
115
|
+
matchType: 'bm25',
|
|
116
|
+
});
|
|
117
|
+
expect(result.score).toBe(1.5);
|
|
118
|
+
expect(result.matchType).toBe('bm25');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe('MemoryEntrySchema', () => {
|
|
122
|
+
it('parses valid entry', () => {
|
|
123
|
+
const entry = MemoryEntrySchema.parse({
|
|
124
|
+
id: 'mem-001',
|
|
125
|
+
content: 'Some content',
|
|
126
|
+
xxhash: 'abcdef0123456789',
|
|
127
|
+
simhash: BigInt('0xdeadbeef'),
|
|
128
|
+
createdAt: Date.now(),
|
|
129
|
+
metadata: { source: 'test' },
|
|
130
|
+
});
|
|
131
|
+
expect(entry.id).toBe('mem-001');
|
|
132
|
+
expect(typeof entry.simhash).toBe('bigint');
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe('DedupResultSchema', () => {
|
|
136
|
+
it('parses exact match', () => {
|
|
137
|
+
const result = DedupResultSchema.parse({
|
|
138
|
+
isDuplicate: true,
|
|
139
|
+
matchType: 'exact',
|
|
140
|
+
existingId: 'mem-001',
|
|
141
|
+
});
|
|
142
|
+
expect(result.isDuplicate).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
it('parses near match', () => {
|
|
145
|
+
const result = DedupResultSchema.parse({
|
|
146
|
+
isDuplicate: true,
|
|
147
|
+
matchType: 'near',
|
|
148
|
+
existingId: 'mem-002',
|
|
149
|
+
hammingDistance: 2,
|
|
150
|
+
});
|
|
151
|
+
expect(result.hammingDistance).toBe(2);
|
|
152
|
+
});
|
|
153
|
+
it('parses no match', () => {
|
|
154
|
+
const result = DedupResultSchema.parse({
|
|
155
|
+
isDuplicate: false,
|
|
156
|
+
matchType: 'none',
|
|
157
|
+
});
|
|
158
|
+
expect(result.existingId).toBeUndefined();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
describe('IndexMetadataSchema', () => {
|
|
162
|
+
it('parses valid metadata', () => {
|
|
163
|
+
const meta = IndexMetadataSchema.parse({
|
|
164
|
+
version: 1,
|
|
165
|
+
rootHash: 'abc123',
|
|
166
|
+
totalFiles: 100,
|
|
167
|
+
totalSymbols: 1500,
|
|
168
|
+
lastUpdated: Date.now(),
|
|
169
|
+
languages: ['typescript', 'javascript'],
|
|
170
|
+
});
|
|
171
|
+
expect(meta.totalFiles).toBe(100);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
describe('RepoMapEntrySchema', () => {
|
|
175
|
+
it('parses valid entry', () => {
|
|
176
|
+
const entry = RepoMapEntrySchema.parse({
|
|
177
|
+
filePath: 'src/index.ts',
|
|
178
|
+
rank: 0.85,
|
|
179
|
+
symbols: [
|
|
180
|
+
{ name: 'main', kind: 'function', line: 1 },
|
|
181
|
+
{ name: 'Config', kind: 'interface', line: 20 },
|
|
182
|
+
],
|
|
183
|
+
});
|
|
184
|
+
expect(entry.symbols).toHaveLength(2);
|
|
185
|
+
expect(entry.rank).toBe(0.85);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { SymbolKindSchema, CodeSymbolSchema, FileASTSchema, FileIndexSchema, SearchQuerySchema, SearchResultSchema, MemoryEntrySchema, DedupResultSchema, IndexMetadataSchema, RepoMapEntrySchema, } from './types.js';
|
|
2
|
+
export type { SymbolKind, CodeSymbol, FileAST, FileIndex, SearchQuery, SearchResult, MemoryEntry, DedupResult, IndexMetadata, RepoMapEntry, } from './types.js';
|
|
3
|
+
export { SymbolExtractor } from './parser/symbol-extractor.js';
|
|
4
|
+
export type { LanguageExtractor } from './parser/symbol-extractor.js';
|
|
5
|
+
export { TypeScriptExtractor } from './parser/typescript-extractor.js';
|
|
6
|
+
export { PythonExtractor } from './parser/python-extractor.js';
|
|
7
|
+
export { GoExtractor } from './parser/go-extractor.js';
|
|
8
|
+
export { RustExtractor } from './parser/rust-extractor.js';
|
|
9
|
+
export { MerkleTree, type MerkleNode } from './indexing/merkle-tree.js';
|
|
10
|
+
export { GitHashProvider } from './indexing/git-hash-provider.js';
|
|
11
|
+
export { ChangeDetector } from './indexing/change-detector.js';
|
|
12
|
+
export { IncrementalIndexer } from './indexing/incremental-indexer.js';
|
|
13
|
+
export { CodeTokenizer } from './search/tokenizer.js';
|
|
14
|
+
export { InvertedIndex } from './search/inverted-index.js';
|
|
15
|
+
export { BM25 } from './search/bm25.js';
|
|
16
|
+
export { SearchEngine } from './search/search-engine.js';
|
|
17
|
+
export { DependencyGraph } from './repo-map/dependency-graph.js';
|
|
18
|
+
export { PageRank } from './repo-map/pagerank.js';
|
|
19
|
+
export { RepoMapGenerator } from './repo-map/repo-map-generator.js';
|
|
20
|
+
export { xxhash64 } from './memory/xxhash.js';
|
|
21
|
+
export { SimHash } from './memory/simhash.js';
|
|
22
|
+
export { DedupPipeline } from './memory/dedup-pipeline.js';
|
|
23
|
+
export type { MemoryStore } from './memory/memory-store.js';
|
|
24
|
+
export { InMemoryStore } from './memory/memory-store.js';
|
|
25
|
+
export { codeIntelligencePlugin } from './plugin/code-intelligence-plugin.js';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,UAAU,EACV,UAAU,EACV,OAAO,EACP,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAG1D,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAGtE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAGnE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAGxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Core types and schemas
|
|
2
|
+
export { SymbolKindSchema, CodeSymbolSchema, FileASTSchema, FileIndexSchema, SearchQuerySchema, SearchResultSchema, MemoryEntrySchema, DedupResultSchema, IndexMetadataSchema, RepoMapEntrySchema, } from './types.js';
|
|
3
|
+
// Parser
|
|
4
|
+
export { SymbolExtractor } from './parser/symbol-extractor.js';
|
|
5
|
+
export { TypeScriptExtractor } from './parser/typescript-extractor.js';
|
|
6
|
+
export { PythonExtractor } from './parser/python-extractor.js';
|
|
7
|
+
export { GoExtractor } from './parser/go-extractor.js';
|
|
8
|
+
export { RustExtractor } from './parser/rust-extractor.js';
|
|
9
|
+
// Indexing
|
|
10
|
+
export { MerkleTree } from './indexing/merkle-tree.js';
|
|
11
|
+
export { GitHashProvider } from './indexing/git-hash-provider.js';
|
|
12
|
+
export { ChangeDetector } from './indexing/change-detector.js';
|
|
13
|
+
export { IncrementalIndexer } from './indexing/incremental-indexer.js';
|
|
14
|
+
// Search
|
|
15
|
+
export { CodeTokenizer } from './search/tokenizer.js';
|
|
16
|
+
export { InvertedIndex } from './search/inverted-index.js';
|
|
17
|
+
export { BM25 } from './search/bm25.js';
|
|
18
|
+
export { SearchEngine } from './search/search-engine.js';
|
|
19
|
+
// Repo Map
|
|
20
|
+
export { DependencyGraph } from './repo-map/dependency-graph.js';
|
|
21
|
+
export { PageRank } from './repo-map/pagerank.js';
|
|
22
|
+
export { RepoMapGenerator } from './repo-map/repo-map-generator.js';
|
|
23
|
+
// Memory
|
|
24
|
+
export { xxhash64 } from './memory/xxhash.js';
|
|
25
|
+
export { SimHash } from './memory/simhash.js';
|
|
26
|
+
export { DedupPipeline } from './memory/dedup-pipeline.js';
|
|
27
|
+
export { InMemoryStore } from './memory/memory-store.js';
|
|
28
|
+
// Plugin
|
|
29
|
+
export { codeIntelligencePlugin } from './plugin/code-intelligence-plugin.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexing.test.d.ts","sourceRoot":"","sources":["../../../../src/indexing/__tests__/indexing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { GitHashProvider } from '../git-hash-provider.js';
|
|
3
|
+
import { MerkleTree } from '../merkle-tree.js';
|
|
4
|
+
import { ChangeDetector } from '../change-detector.js';
|
|
5
|
+
import { IncrementalIndexer } from '../incremental-indexer.js';
|
|
6
|
+
import { SymbolExtractor } from '../../parser/symbol-extractor.js';
|
|
7
|
+
describe('GitHashProvider', () => {
|
|
8
|
+
const provider = new GitHashProvider();
|
|
9
|
+
it('produces consistent hashes', () => {
|
|
10
|
+
const hash1 = provider.hashContent('hello world');
|
|
11
|
+
const hash2 = provider.hashContent('hello world');
|
|
12
|
+
expect(hash1).toBe(hash2);
|
|
13
|
+
});
|
|
14
|
+
it('produces different hashes for different content', () => {
|
|
15
|
+
const hash1 = provider.hashContent('hello');
|
|
16
|
+
const hash2 = provider.hashContent('world');
|
|
17
|
+
expect(hash1).not.toBe(hash2);
|
|
18
|
+
});
|
|
19
|
+
it('produces 40-char hex string (SHA-1)', () => {
|
|
20
|
+
const hash = provider.hashContent('test');
|
|
21
|
+
expect(hash).toMatch(/^[0-9a-f]{40}$/);
|
|
22
|
+
});
|
|
23
|
+
it('matches git hash-object format', () => {
|
|
24
|
+
// git hash-object computes sha1("blob <size>\0<content>")
|
|
25
|
+
// "hello world" -> blob 11\0hello world
|
|
26
|
+
const hash = provider.hashContent('hello world');
|
|
27
|
+
expect(hash).toHaveLength(40);
|
|
28
|
+
});
|
|
29
|
+
it('hashes directory from child hashes', () => {
|
|
30
|
+
const hash = provider.hashDirectory(['abc123', 'def456']);
|
|
31
|
+
expect(hash).toMatch(/^[0-9a-f]{40}$/);
|
|
32
|
+
});
|
|
33
|
+
it('directory hash is order-independent (sorted)', () => {
|
|
34
|
+
const hash1 = provider.hashDirectory(['abc', 'def']);
|
|
35
|
+
const hash2 = provider.hashDirectory(['def', 'abc']);
|
|
36
|
+
expect(hash1).toBe(hash2);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe('MerkleTree', () => {
|
|
40
|
+
it('builds from files', () => {
|
|
41
|
+
const files = new Map([
|
|
42
|
+
['src/index.ts', 'export const x = 1'],
|
|
43
|
+
['src/utils.ts', 'export function foo() {}'],
|
|
44
|
+
]);
|
|
45
|
+
const tree = MerkleTree.fromFiles(files);
|
|
46
|
+
expect(tree.getRootHash()).toBeTruthy();
|
|
47
|
+
expect(tree.getFiles().size).toBe(2);
|
|
48
|
+
});
|
|
49
|
+
it('same files produce same root hash', () => {
|
|
50
|
+
const files = new Map([
|
|
51
|
+
['a.ts', 'content a'],
|
|
52
|
+
['b.ts', 'content b'],
|
|
53
|
+
]);
|
|
54
|
+
const tree1 = MerkleTree.fromFiles(files);
|
|
55
|
+
const tree2 = MerkleTree.fromFiles(files);
|
|
56
|
+
expect(tree1.getRootHash()).toBe(tree2.getRootHash());
|
|
57
|
+
});
|
|
58
|
+
it('different files produce different root hash', () => {
|
|
59
|
+
const tree1 = MerkleTree.fromFiles(new Map([['a.ts', 'v1']]));
|
|
60
|
+
const tree2 = MerkleTree.fromFiles(new Map([['a.ts', 'v2']]));
|
|
61
|
+
expect(tree1.getRootHash()).not.toBe(tree2.getRootHash());
|
|
62
|
+
});
|
|
63
|
+
it('retrieves node by path', () => {
|
|
64
|
+
const files = new Map([['src/lib/util.ts', 'content']]);
|
|
65
|
+
const tree = MerkleTree.fromFiles(files);
|
|
66
|
+
const node = tree.getNode('src/lib/util.ts');
|
|
67
|
+
expect(node).toBeDefined();
|
|
68
|
+
expect(node.isDirectory).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
it('retrieves directory node', () => {
|
|
71
|
+
const files = new Map([
|
|
72
|
+
['src/a.ts', 'a'],
|
|
73
|
+
['src/b.ts', 'b'],
|
|
74
|
+
]);
|
|
75
|
+
const tree = MerkleTree.fromFiles(files);
|
|
76
|
+
const dir = tree.getNode('src');
|
|
77
|
+
expect(dir).toBeDefined();
|
|
78
|
+
expect(dir.isDirectory).toBe(true);
|
|
79
|
+
expect(dir.children.size).toBe(2);
|
|
80
|
+
});
|
|
81
|
+
it('builds from pre-computed hashes', () => {
|
|
82
|
+
const hashes = new Map([
|
|
83
|
+
['a.ts', 'abc123'],
|
|
84
|
+
['b.ts', 'def456'],
|
|
85
|
+
]);
|
|
86
|
+
const tree = MerkleTree.fromHashes(hashes);
|
|
87
|
+
expect(tree.getRootHash()).toBeTruthy();
|
|
88
|
+
const files = tree.getFiles();
|
|
89
|
+
expect(files.get('a.ts')).toBe('abc123');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('ChangeDetector', () => {
|
|
93
|
+
const detector = new ChangeDetector();
|
|
94
|
+
it('detects added files', () => {
|
|
95
|
+
const old = MerkleTree.fromFiles(new Map([['a.ts', 'a']]));
|
|
96
|
+
const nw = MerkleTree.fromFiles(new Map([['a.ts', 'a'], ['b.ts', 'b']]));
|
|
97
|
+
const changes = detector.detect(old, nw);
|
|
98
|
+
expect(changes.added).toEqual(['b.ts']);
|
|
99
|
+
expect(changes.modified).toEqual([]);
|
|
100
|
+
expect(changes.deleted).toEqual([]);
|
|
101
|
+
});
|
|
102
|
+
it('detects modified files', () => {
|
|
103
|
+
const old = MerkleTree.fromFiles(new Map([['a.ts', 'v1']]));
|
|
104
|
+
const nw = MerkleTree.fromFiles(new Map([['a.ts', 'v2']]));
|
|
105
|
+
const changes = detector.detect(old, nw);
|
|
106
|
+
expect(changes.modified).toEqual(['a.ts']);
|
|
107
|
+
expect(changes.added).toEqual([]);
|
|
108
|
+
});
|
|
109
|
+
it('detects deleted files', () => {
|
|
110
|
+
const old = MerkleTree.fromFiles(new Map([['a.ts', 'a'], ['b.ts', 'b']]));
|
|
111
|
+
const nw = MerkleTree.fromFiles(new Map([['a.ts', 'a']]));
|
|
112
|
+
const changes = detector.detect(old, nw);
|
|
113
|
+
expect(changes.deleted).toEqual(['b.ts']);
|
|
114
|
+
});
|
|
115
|
+
it('detects mixed changes', () => {
|
|
116
|
+
const old = MerkleTree.fromFiles(new Map([
|
|
117
|
+
['keep.ts', 'same'],
|
|
118
|
+
['modify.ts', 'old'],
|
|
119
|
+
['delete.ts', 'gone'],
|
|
120
|
+
]));
|
|
121
|
+
const nw = MerkleTree.fromFiles(new Map([
|
|
122
|
+
['keep.ts', 'same'],
|
|
123
|
+
['modify.ts', 'new'],
|
|
124
|
+
['add.ts', 'new file'],
|
|
125
|
+
]));
|
|
126
|
+
const changes = detector.detect(old, nw);
|
|
127
|
+
expect(changes.added).toEqual(['add.ts']);
|
|
128
|
+
expect(changes.modified).toEqual(['modify.ts']);
|
|
129
|
+
expect(changes.deleted).toEqual(['delete.ts']);
|
|
130
|
+
});
|
|
131
|
+
it('reports identical trees', () => {
|
|
132
|
+
const files = new Map([['a.ts', 'content']]);
|
|
133
|
+
const tree = MerkleTree.fromFiles(files);
|
|
134
|
+
expect(detector.isIdentical(tree, tree)).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
it('reports different trees', () => {
|
|
137
|
+
const tree1 = MerkleTree.fromFiles(new Map([['a.ts', 'v1']]));
|
|
138
|
+
const tree2 = MerkleTree.fromFiles(new Map([['a.ts', 'v2']]));
|
|
139
|
+
expect(detector.isIdentical(tree1, tree2)).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('IncrementalIndexer', () => {
|
|
143
|
+
it('indexes all files on first run', async () => {
|
|
144
|
+
const extractor = new SymbolExtractor();
|
|
145
|
+
const indexer = new IncrementalIndexer(extractor);
|
|
146
|
+
const files = new Map([
|
|
147
|
+
['src/main.ts', 'export function main() {}'],
|
|
148
|
+
['src/utils.ts', 'export const helper = () => 42'],
|
|
149
|
+
]);
|
|
150
|
+
const result = await indexer.index(files);
|
|
151
|
+
expect(result.changes.added).toHaveLength(2);
|
|
152
|
+
expect(result.changes.modified).toHaveLength(0);
|
|
153
|
+
expect(result.indexed).toHaveLength(2);
|
|
154
|
+
expect(result.metadata.totalFiles).toBe(2);
|
|
155
|
+
});
|
|
156
|
+
it('only re-indexes changed files', async () => {
|
|
157
|
+
const extractor = new SymbolExtractor();
|
|
158
|
+
const indexer = new IncrementalIndexer(extractor);
|
|
159
|
+
// First run
|
|
160
|
+
const files1 = new Map([
|
|
161
|
+
['a.ts', 'export const x = 1'],
|
|
162
|
+
['b.ts', 'export const y = 2'],
|
|
163
|
+
]);
|
|
164
|
+
await indexer.index(files1);
|
|
165
|
+
// Second run with b.ts modified
|
|
166
|
+
const files2 = new Map([
|
|
167
|
+
['a.ts', 'export const x = 1'],
|
|
168
|
+
['b.ts', 'export const y = 3'],
|
|
169
|
+
]);
|
|
170
|
+
const result = await indexer.index(files2);
|
|
171
|
+
expect(result.changes.added).toHaveLength(0);
|
|
172
|
+
expect(result.changes.modified).toEqual(['b.ts']);
|
|
173
|
+
expect(result.indexed).toHaveLength(1);
|
|
174
|
+
expect(result.indexed[0].filePath).toBe('b.ts');
|
|
175
|
+
});
|
|
176
|
+
it('detects deleted files', async () => {
|
|
177
|
+
const extractor = new SymbolExtractor();
|
|
178
|
+
const indexer = new IncrementalIndexer(extractor);
|
|
179
|
+
await indexer.index(new Map([['a.ts', 'x'], ['b.ts', 'y']]));
|
|
180
|
+
const result = await indexer.index(new Map([['a.ts', 'x']]));
|
|
181
|
+
expect(result.changes.deleted).toEqual(['b.ts']);
|
|
182
|
+
expect(result.metadata.totalFiles).toBe(1);
|
|
183
|
+
});
|
|
184
|
+
it('returns all symbols', async () => {
|
|
185
|
+
const extractor = new SymbolExtractor();
|
|
186
|
+
const indexer = new IncrementalIndexer(extractor);
|
|
187
|
+
await indexer.index(new Map([
|
|
188
|
+
['a.ts', 'export function foo() {}\nexport function bar() {}'],
|
|
189
|
+
]));
|
|
190
|
+
const symbols = indexer.getAllSymbols();
|
|
191
|
+
expect(symbols.length).toBeGreaterThanOrEqual(2);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MerkleTree } from './merkle-tree.js';
|
|
2
|
+
export interface ChangeSet {
|
|
3
|
+
added: string[];
|
|
4
|
+
modified: string[];
|
|
5
|
+
deleted: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Diff two Merkle trees to identify changed files.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ChangeDetector {
|
|
11
|
+
/** Compare old and new trees, returning the set of changes. */
|
|
12
|
+
detect(oldTree: MerkleTree, newTree: MerkleTree): ChangeSet;
|
|
13
|
+
/** Quick check if trees are identical (root hash comparison). */
|
|
14
|
+
isIdentical(oldTree: MerkleTree, newTree: MerkleTree): boolean;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=change-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-detector.d.ts","sourceRoot":"","sources":["../../../src/indexing/change-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,+DAA+D;IAC/D,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,SAAS;IAgC3D,iEAAiE;IACjE,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO;CAG/D"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff two Merkle trees to identify changed files.
|
|
3
|
+
*/
|
|
4
|
+
export class ChangeDetector {
|
|
5
|
+
/** Compare old and new trees, returning the set of changes. */
|
|
6
|
+
detect(oldTree, newTree) {
|
|
7
|
+
const oldFiles = oldTree.getFiles();
|
|
8
|
+
const newFiles = newTree.getFiles();
|
|
9
|
+
const added = [];
|
|
10
|
+
const modified = [];
|
|
11
|
+
const deleted = [];
|
|
12
|
+
// Find added and modified files
|
|
13
|
+
for (const [path, newHash] of newFiles) {
|
|
14
|
+
const oldHash = oldFiles.get(path);
|
|
15
|
+
if (oldHash === undefined) {
|
|
16
|
+
added.push(path);
|
|
17
|
+
}
|
|
18
|
+
else if (oldHash !== newHash) {
|
|
19
|
+
modified.push(path);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Find deleted files
|
|
23
|
+
for (const path of oldFiles.keys()) {
|
|
24
|
+
if (!newFiles.has(path)) {
|
|
25
|
+
deleted.push(path);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
added: added.sort(),
|
|
30
|
+
modified: modified.sort(),
|
|
31
|
+
deleted: deleted.sort(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Quick check if trees are identical (root hash comparison). */
|
|
35
|
+
isIdentical(oldTree, newTree) {
|
|
36
|
+
return oldTree.getRootHash() === newTree.getRootHash();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute git-compatible object hashes for files.
|
|
3
|
+
* Git uses: sha1("blob <size>\0<content>")
|
|
4
|
+
*/
|
|
5
|
+
export declare class GitHashProvider {
|
|
6
|
+
/** Compute git blob hash for content (matches `git hash-object`). */
|
|
7
|
+
hashContent(content: string): string;
|
|
8
|
+
/** Compute a hash for a directory node (sorted child hashes). */
|
|
9
|
+
hashDirectory(childHashes: string[]): string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=git-hash-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hash-provider.d.ts","sourceRoot":"","sources":["../../../src/indexing/git-hash-provider.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,eAAe;IAC1B,qEAAqE;IACrE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IASpC,iEAAiE;IACjE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM;CAQ7C"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Compute git-compatible object hashes for files.
|
|
4
|
+
* Git uses: sha1("blob <size>\0<content>")
|
|
5
|
+
*/
|
|
6
|
+
export class GitHashProvider {
|
|
7
|
+
/** Compute git blob hash for content (matches `git hash-object`). */
|
|
8
|
+
hashContent(content) {
|
|
9
|
+
const buffer = Buffer.from(content);
|
|
10
|
+
const header = `blob ${buffer.length}\0`;
|
|
11
|
+
const hash = createHash('sha1');
|
|
12
|
+
hash.update(header);
|
|
13
|
+
hash.update(buffer);
|
|
14
|
+
return hash.digest('hex');
|
|
15
|
+
}
|
|
16
|
+
/** Compute a hash for a directory node (sorted child hashes). */
|
|
17
|
+
hashDirectory(childHashes) {
|
|
18
|
+
const sorted = [...childHashes].sort();
|
|
19
|
+
const combined = sorted.join('\n');
|
|
20
|
+
const hash = createHash('sha1');
|
|
21
|
+
hash.update(`tree ${combined.length}\0`);
|
|
22
|
+
hash.update(combined);
|
|
23
|
+
return hash.digest('hex');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { FileIndex, IndexMetadata, CodeSymbol } from '../types.js';
|
|
2
|
+
import { type ChangeSet } from './change-detector.js';
|
|
3
|
+
import { SymbolExtractor } from '../parser/symbol-extractor.js';
|
|
4
|
+
export interface IndexerOptions {
|
|
5
|
+
indexDir?: string;
|
|
6
|
+
filePatterns?: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Orchestrates incremental re-indexing of only changed files.
|
|
10
|
+
* Persists index to `.agentfactory/code-index/`.
|
|
11
|
+
*/
|
|
12
|
+
export declare class IncrementalIndexer {
|
|
13
|
+
private hashProvider;
|
|
14
|
+
private changeDetector;
|
|
15
|
+
private extractor;
|
|
16
|
+
private indexDir;
|
|
17
|
+
private previousTree;
|
|
18
|
+
private fileIndex;
|
|
19
|
+
constructor(extractor: SymbolExtractor, options?: IndexerOptions);
|
|
20
|
+
/**
|
|
21
|
+
* Index files, returning only the changed ones.
|
|
22
|
+
* @param files Map of filePath -> content
|
|
23
|
+
*/
|
|
24
|
+
index(files: Map<string, string>): Promise<{
|
|
25
|
+
changes: ChangeSet;
|
|
26
|
+
indexed: FileIndex[];
|
|
27
|
+
metadata: IndexMetadata;
|
|
28
|
+
}>;
|
|
29
|
+
/** Save index to disk. */
|
|
30
|
+
save(basePath: string): Promise<void>;
|
|
31
|
+
/** Load index from disk. */
|
|
32
|
+
load(basePath: string): Promise<boolean>;
|
|
33
|
+
/** Get all indexed symbols. */
|
|
34
|
+
getAllSymbols(): CodeSymbol[];
|
|
35
|
+
/** Get the current file index. */
|
|
36
|
+
getFileIndex(): Map<string, FileIndex>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=incremental-indexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incremental-indexer.d.ts","sourceRoot":"","sources":["../../../src/indexing/incremental-indexer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAErE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,SAAS,CAAoC;gBAEzC,SAAS,EAAE,eAAe,EAAE,OAAO,GAAE,cAAmB;IAKpE;;;OAGG;IACG,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;QAC/C,OAAO,EAAE,SAAS,CAAA;QAClB,OAAO,EAAE,SAAS,EAAE,CAAA;QACpB,QAAQ,EAAE,aAAa,CAAA;KACxB,CAAC;IA+DF,0BAA0B;IACpB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3C,4BAA4B;IACtB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB9C,+BAA+B;IAC/B,aAAa,IAAI,UAAU,EAAE;IAQ7B,kCAAkC;IAClC,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;CAGvC"}
|