@mmnto/totem 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/dist/chunkers/chunker.d.ts +12 -0
- package/dist/chunkers/chunker.d.ts.map +1 -0
- package/dist/chunkers/chunker.js +17 -0
- package/dist/chunkers/chunker.js.map +1 -0
- package/dist/chunkers/markdown-chunker.d.ts +17 -0
- package/dist/chunkers/markdown-chunker.d.ts.map +1 -0
- package/dist/chunkers/markdown-chunker.js +120 -0
- package/dist/chunkers/markdown-chunker.js.map +1 -0
- package/dist/chunkers/schema-file-chunker.d.ts +15 -0
- package/dist/chunkers/schema-file-chunker.d.ts.map +1 -0
- package/dist/chunkers/schema-file-chunker.js +55 -0
- package/dist/chunkers/schema-file-chunker.js.map +1 -0
- package/dist/chunkers/session-log-chunker.d.ts +14 -0
- package/dist/chunkers/session-log-chunker.d.ts.map +1 -0
- package/dist/chunkers/session-log-chunker.js +78 -0
- package/dist/chunkers/session-log-chunker.js.map +1 -0
- package/dist/chunkers/test-file-chunker.d.ts +17 -0
- package/dist/chunkers/test-file-chunker.d.ts.map +1 -0
- package/dist/chunkers/test-file-chunker.js +66 -0
- package/dist/chunkers/test-file-chunker.js.map +1 -0
- package/dist/chunkers/typescript-chunker.d.ts +17 -0
- package/dist/chunkers/typescript-chunker.d.ts.map +1 -0
- package/dist/chunkers/typescript-chunker.js +94 -0
- package/dist/chunkers/typescript-chunker.js.map +1 -0
- package/dist/config-schema.d.ts +229 -0
- package/dist/config-schema.d.ts.map +1 -0
- package/dist/config-schema.js +56 -0
- package/dist/config-schema.js.map +1 -0
- package/dist/embedders/embedder.d.ts +15 -0
- package/dist/embedders/embedder.d.ts.map +1 -0
- package/dist/embedders/embedder.js +11 -0
- package/dist/embedders/embedder.js.map +1 -0
- package/dist/embedders/ollama-embedder.d.ts +14 -0
- package/dist/embedders/ollama-embedder.d.ts.map +1 -0
- package/dist/embedders/ollama-embedder.js +67 -0
- package/dist/embedders/ollama-embedder.js.map +1 -0
- package/dist/embedders/openai-embedder.d.ts +9 -0
- package/dist/embedders/openai-embedder.d.ts.map +1 -0
- package/dist/embedders/openai-embedder.js +36 -0
- package/dist/embedders/openai-embedder.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/file-resolver.d.ts +14 -0
- package/dist/ingest/file-resolver.d.ts.map +1 -0
- package/dist/ingest/file-resolver.js +54 -0
- package/dist/ingest/file-resolver.js.map +1 -0
- package/dist/ingest/pipeline.d.ts +7 -0
- package/dist/ingest/pipeline.d.ts.map +1 -0
- package/dist/ingest/pipeline.js +79 -0
- package/dist/ingest/pipeline.js.map +1 -0
- package/dist/ingest/sync.d.ts +4 -0
- package/dist/ingest/sync.d.ts.map +1 -0
- package/dist/ingest/sync.js +3 -0
- package/dist/ingest/sync.js.map +1 -0
- package/dist/store/lance-schema.d.ts +42 -0
- package/dist/store/lance-schema.d.ts.map +1 -0
- package/dist/store/lance-schema.js +21 -0
- package/dist/store/lance-schema.js.map +1 -0
- package/dist/store/lance-store.d.ts +27 -0
- package/dist/store/lance-store.d.ts.map +1 -0
- package/dist/store/lance-store.js +106 -0
- package/dist/store/lance-store.js.map +1 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChunkStrategy, ContentType } from '../config-schema.js';
|
|
2
|
+
import type { Chunk } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* All chunkers implement this interface.
|
|
5
|
+
* Given file content and metadata, produce an array of Chunks.
|
|
6
|
+
*/
|
|
7
|
+
export interface Chunker {
|
|
8
|
+
readonly strategy: ChunkStrategy;
|
|
9
|
+
chunk(content: string, filePath: string, type: ContentType): Chunk[];
|
|
10
|
+
}
|
|
11
|
+
export declare function createChunker(strategy: ChunkStrategy): Chunker;
|
|
12
|
+
//# sourceMappingURL=chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.d.ts","sourceRoot":"","sources":["../../src/chunkers/chunker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAOzC;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IAEjC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,CAAC;CACtE;AAUD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAG9D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MarkdownChunker } from './markdown-chunker.js';
|
|
2
|
+
import { SchemaFileChunker } from './schema-file-chunker.js';
|
|
3
|
+
import { SessionLogChunker } from './session-log-chunker.js';
|
|
4
|
+
import { TestFileChunker } from './test-file-chunker.js';
|
|
5
|
+
import { TypeScriptChunker } from './typescript-chunker.js';
|
|
6
|
+
const CHUNKER_MAP = {
|
|
7
|
+
'session-log': SessionLogChunker,
|
|
8
|
+
'markdown-heading': MarkdownChunker,
|
|
9
|
+
'typescript-ast': TypeScriptChunker,
|
|
10
|
+
'schema-file': SchemaFileChunker,
|
|
11
|
+
'test-file': TestFileChunker,
|
|
12
|
+
};
|
|
13
|
+
export function createChunker(strategy) {
|
|
14
|
+
const Ctor = CHUNKER_MAP[strategy];
|
|
15
|
+
return new Ctor();
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.js","sourceRoot":"","sources":["../../src/chunkers/chunker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAY5D,MAAM,WAAW,GAA6C;IAC5D,aAAa,EAAE,iBAAiB;IAChC,kBAAkB,EAAE,eAAe;IACnC,gBAAgB,EAAE,iBAAiB;IACnC,aAAa,EAAE,iBAAiB;IAChC,WAAW,EAAE,eAAe;CAC7B,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,QAAuB;IACnD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACnC,OAAO,IAAI,IAAI,EAAE,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChunkStrategy, ContentType } from '../config-schema.js';
|
|
2
|
+
import type { Chunk } from '../types.js';
|
|
3
|
+
import type { Chunker } from './chunker.js';
|
|
4
|
+
/**
|
|
5
|
+
* Markdown Heading Chunker.
|
|
6
|
+
*
|
|
7
|
+
* Chunks by ## and ### heading boundaries.
|
|
8
|
+
* Extracts YAML frontmatter as metadata on every chunk.
|
|
9
|
+
*/
|
|
10
|
+
export declare class MarkdownChunker implements Chunker {
|
|
11
|
+
readonly strategy: ChunkStrategy;
|
|
12
|
+
private onWarn;
|
|
13
|
+
constructor(onWarn?: (msg: string) => void);
|
|
14
|
+
chunk(content: string, filePath: string, type: ContentType): Chunk[];
|
|
15
|
+
private extractFrontmatter;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=markdown-chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-chunker.d.ts","sourceRoot":"","sources":["../../src/chunkers/markdown-chunker.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAI5C;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,OAAO;IAC7C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAsB;IACtD,OAAO,CAAC,MAAM,CAAsC;gBAExC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI;IAI1C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE;IAkEpE,OAAO,CAAC,kBAAkB;CAuB3B"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import remarkFrontmatter from 'remark-frontmatter';
|
|
2
|
+
import remarkParse from 'remark-parse';
|
|
3
|
+
import { unified } from 'unified';
|
|
4
|
+
import YAML from 'yaml';
|
|
5
|
+
const MAX_SPLIT_DEPTH = 3;
|
|
6
|
+
/**
|
|
7
|
+
* Markdown Heading Chunker.
|
|
8
|
+
*
|
|
9
|
+
* Chunks by ## and ### heading boundaries.
|
|
10
|
+
* Extracts YAML frontmatter as metadata on every chunk.
|
|
11
|
+
*/
|
|
12
|
+
export class MarkdownChunker {
|
|
13
|
+
strategy = 'markdown-heading';
|
|
14
|
+
onWarn;
|
|
15
|
+
constructor(onWarn) {
|
|
16
|
+
this.onWarn = onWarn;
|
|
17
|
+
}
|
|
18
|
+
chunk(content, filePath, type) {
|
|
19
|
+
const tree = unified().use(remarkParse).use(remarkFrontmatter, ['yaml']).parse(content);
|
|
20
|
+
const metadata = this.extractFrontmatter(tree, filePath);
|
|
21
|
+
const chunks = [];
|
|
22
|
+
const lines = content.split('\n');
|
|
23
|
+
let currentHeading = null;
|
|
24
|
+
let sectionNodes = [];
|
|
25
|
+
let sectionStartLine = 1;
|
|
26
|
+
const flush = () => {
|
|
27
|
+
if (sectionNodes.length === 0 && !currentHeading)
|
|
28
|
+
return;
|
|
29
|
+
const sectionText = sectionNodes
|
|
30
|
+
.map((n) => nodeToSourceText(n, lines))
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.join('\n\n');
|
|
33
|
+
if (!sectionText.trim())
|
|
34
|
+
return;
|
|
35
|
+
const label = currentHeading ?? filePath;
|
|
36
|
+
const contextPrefix = `File: ${filePath} | Section: ${label}`;
|
|
37
|
+
const endLine = sectionNodes.length > 0
|
|
38
|
+
? (sectionNodes[sectionNodes.length - 1].position?.end.line ?? sectionStartLine)
|
|
39
|
+
: sectionStartLine;
|
|
40
|
+
chunks.push({
|
|
41
|
+
content: sectionText.trim(),
|
|
42
|
+
contextPrefix,
|
|
43
|
+
filePath,
|
|
44
|
+
type,
|
|
45
|
+
strategy: this.strategy,
|
|
46
|
+
label,
|
|
47
|
+
startLine: sectionStartLine,
|
|
48
|
+
endLine,
|
|
49
|
+
metadata,
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
for (const node of tree.children) {
|
|
53
|
+
// Skip YAML frontmatter node
|
|
54
|
+
if (node.type === 'yaml')
|
|
55
|
+
continue;
|
|
56
|
+
if (node.type === 'heading') {
|
|
57
|
+
const h = node;
|
|
58
|
+
// Only split on headings up to depth 3
|
|
59
|
+
if (h.depth <= MAX_SPLIT_DEPTH) {
|
|
60
|
+
flush();
|
|
61
|
+
currentHeading = extractPlainText(h.children);
|
|
62
|
+
sectionNodes = [];
|
|
63
|
+
sectionStartLine = h.position?.start.line ?? 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
sectionNodes.push(node);
|
|
68
|
+
}
|
|
69
|
+
// Flush final section
|
|
70
|
+
flush();
|
|
71
|
+
return chunks;
|
|
72
|
+
}
|
|
73
|
+
extractFrontmatter(tree, filePath) {
|
|
74
|
+
const yamlNode = tree.children.find((n) => n.type === 'yaml');
|
|
75
|
+
if (!yamlNode || !('value' in yamlNode))
|
|
76
|
+
return {};
|
|
77
|
+
try {
|
|
78
|
+
const parsed = YAML.parse(yamlNode.value);
|
|
79
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
80
|
+
return {};
|
|
81
|
+
const result = {};
|
|
82
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
83
|
+
result[key] = String(value);
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const msg = `Failed to parse frontmatter in ${filePath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
89
|
+
if (this.onWarn) {
|
|
90
|
+
this.onWarn(msg);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.warn(`[Totem Warning] ${msg}`);
|
|
94
|
+
}
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function extractPlainText(nodes) {
|
|
100
|
+
return nodes
|
|
101
|
+
.map((n) => {
|
|
102
|
+
if (n.type === 'text')
|
|
103
|
+
return n.value;
|
|
104
|
+
if ('children' in n)
|
|
105
|
+
return extractPlainText(n.children);
|
|
106
|
+
return '';
|
|
107
|
+
})
|
|
108
|
+
.join('');
|
|
109
|
+
}
|
|
110
|
+
function nodeToSourceText(node, lines) {
|
|
111
|
+
if (node.position) {
|
|
112
|
+
const startIdx = node.position.start.line - 1;
|
|
113
|
+
const endIdx = node.position.end.line;
|
|
114
|
+
return lines.slice(startIdx, endIdx).join('\n');
|
|
115
|
+
}
|
|
116
|
+
if ('value' in node && typeof node.value === 'string')
|
|
117
|
+
return node.value;
|
|
118
|
+
return '';
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=markdown-chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-chunker.js","sourceRoot":"","sources":["../../src/chunkers/markdown-chunker.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,MAAM,oBAAoB,CAAC;AACnD,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,MAAM,CAAC;AAMxB,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,OAAO,eAAe;IACjB,QAAQ,GAAkB,kBAAkB,CAAC;IAC9C,MAAM,CAAsC;IAEpD,YAAY,MAA8B;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,QAAgB,EAAE,IAAiB;QACxD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAS,CAAC;QAEhG,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,IAAI,cAAc,GAAkB,IAAI,CAAC;QACzC,IAAI,YAAY,GAAc,EAAE,CAAC;QACjC,IAAI,gBAAgB,GAAG,CAAC,CAAC;QAEzB,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc;gBAAE,OAAO;YAEzD,MAAM,WAAW,GAAG,YAAY;iBAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;iBACtC,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,MAAM,CAAC,CAAC;YAEhB,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;gBAAE,OAAO;YAEhC,MAAM,KAAK,GAAG,cAAc,IAAI,QAAQ,CAAC;YACzC,MAAM,aAAa,GAAG,SAAS,QAAQ,eAAe,KAAK,EAAE,CAAC;YAC9D,MAAM,OAAO,GACX,YAAY,CAAC,MAAM,GAAG,CAAC;gBACrB,CAAC,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,IAAI,gBAAgB,CAAC;gBACjF,CAAC,CAAC,gBAAgB,CAAC;YAEvB,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE;gBAC3B,aAAa;gBACb,QAAQ;gBACR,IAAI;gBACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,KAAK;gBACL,SAAS,EAAE,gBAAgB;gBAC3B,OAAO;gBACP,QAAQ;aACT,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,6BAA6B;YAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS;YAEnC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,MAAM,CAAC,GAAG,IAAe,CAAC;gBAC1B,uCAAuC;gBACvC,IAAI,CAAC,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC;oBAC/B,KAAK,EAAE,CAAC;oBACR,cAAc,GAAG,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;oBAC9C,YAAY,GAAG,EAAE,CAAC;oBAClB,gBAAgB,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;oBAC/C,SAAS;gBACX,CAAC;YACH,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAED,sBAAsB;QACtB,KAAK,EAAE,CAAC;QAER,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,kBAAkB,CAAC,IAAU,EAAE,QAAgB;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAEnD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAe,CAAC,CAAC;YACpD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;YAE7D,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,kCAAkC,QAAQ,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9G,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;YACzC,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAED,SAAS,gBAAgB,CAAC,KAAwB;IAChD,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,CAAC,CAAC,KAAK,CAAC;QACtC,IAAI,UAAU,IAAI,CAAC;YAAE,OAAO,gBAAgB,CAAC,CAAC,CAAC,QAA6B,CAAC,CAAC;QAC9E,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAa,EAAE,KAAe;IACtD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QACtC,OAAO,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC;IACzE,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ChunkStrategy, ContentType } from '../config-schema.js';
|
|
2
|
+
import type { Chunk } from '../types.js';
|
|
3
|
+
import type { Chunker } from './chunker.js';
|
|
4
|
+
/**
|
|
5
|
+
* Schema File Chunker.
|
|
6
|
+
*
|
|
7
|
+
* Chunks by exported table/relation declarations (Drizzle pgTable, Prisma, etc.).
|
|
8
|
+
* Falls back to chunking by each exported statement.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SchemaFileChunker implements Chunker {
|
|
11
|
+
readonly strategy: ChunkStrategy;
|
|
12
|
+
chunk(content: string, filePath: string, type: ContentType): Chunk[];
|
|
13
|
+
private isExported;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=schema-file-chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-file-chunker.d.ts","sourceRoot":"","sources":["../../src/chunkers/schema-file-chunker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IAC/C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAiB;IAEjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE;IAqDpE,OAAO,CAAC,UAAU;CAKnB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Schema File Chunker.
|
|
4
|
+
*
|
|
5
|
+
* Chunks by exported table/relation declarations (Drizzle pgTable, Prisma, etc.).
|
|
6
|
+
* Falls back to chunking by each exported statement.
|
|
7
|
+
*/
|
|
8
|
+
export class SchemaFileChunker {
|
|
9
|
+
strategy = 'schema-file';
|
|
10
|
+
chunk(content, filePath, type) {
|
|
11
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
12
|
+
const chunks = [];
|
|
13
|
+
const lines = content.split('\n');
|
|
14
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
15
|
+
if (!this.isExported(node))
|
|
16
|
+
return;
|
|
17
|
+
let name = 'unknown';
|
|
18
|
+
if (ts.isVariableStatement(node)) {
|
|
19
|
+
for (const decl of node.declarationList.declarations) {
|
|
20
|
+
if (ts.isIdentifier(decl.name)) {
|
|
21
|
+
name = decl.name.text;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else if ((ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node)) &&
|
|
26
|
+
node.name) {
|
|
27
|
+
name = node.name.text;
|
|
28
|
+
}
|
|
29
|
+
const startPos = node.getStart(sourceFile);
|
|
30
|
+
const endPos = node.getEnd();
|
|
31
|
+
const startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line + 1;
|
|
32
|
+
const endLine = sourceFile.getLineAndCharacterOfPosition(endPos).line + 1;
|
|
33
|
+
const text = lines.slice(startLine - 1, endLine).join('\n');
|
|
34
|
+
chunks.push({
|
|
35
|
+
content: text,
|
|
36
|
+
contextPrefix: `File: ${filePath} | Schema: ${name}`,
|
|
37
|
+
filePath,
|
|
38
|
+
type,
|
|
39
|
+
strategy: this.strategy,
|
|
40
|
+
label: `schema: ${name}`,
|
|
41
|
+
startLine,
|
|
42
|
+
endLine,
|
|
43
|
+
metadata: { name },
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
return chunks;
|
|
47
|
+
}
|
|
48
|
+
isExported(node) {
|
|
49
|
+
if (!ts.canHaveModifiers(node))
|
|
50
|
+
return false;
|
|
51
|
+
const modifiers = ts.getModifiers(node);
|
|
52
|
+
return modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=schema-file-chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-file-chunker.js","sourceRoot":"","sources":["../../src/chunkers/schema-file-chunker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAM5B;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IACnB,QAAQ,GAAkB,aAAa,CAAC;IAEjD,KAAK,CAAC,OAAe,EAAE,QAAgB,EAAE,IAAiB;QACxD,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CACpC,QAAQ,EACR,OAAO,EACP,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,EACJ,EAAE,CAAC,UAAU,CAAC,EAAE,CACjB,CAAC;QAEF,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;YACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO;YAEnC,IAAI,IAAI,GAAG,SAAS,CAAC;YAErB,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,CAAC;oBACrD,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC/B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;oBACxB,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,IACL,CAAC,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;gBACpE,IAAI,CAAC,IAAI,EACT,CAAC;gBACD,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACxB,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,UAAU,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YAC9E,MAAM,OAAO,GAAG,UAAU,CAAC,6BAA6B,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YAE1E,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE5D,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,IAAI;gBACb,aAAa,EAAE,SAAS,QAAQ,cAAc,IAAI,EAAE;gBACpD,QAAQ;gBACR,IAAI;gBACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,KAAK,EAAE,WAAW,IAAI,EAAE;gBACxB,SAAS;gBACT,OAAO;gBACP,QAAQ,EAAE,EAAE,IAAI,EAAE;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,UAAU,CAAC,IAAa;QAC9B,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7C,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;IACjF,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ChunkStrategy, ContentType } from '../config-schema.js';
|
|
2
|
+
import type { Chunk } from '../types.js';
|
|
3
|
+
import type { Chunker } from './chunker.js';
|
|
4
|
+
/**
|
|
5
|
+
* Session Log Chunker — the most critical chunker.
|
|
6
|
+
*
|
|
7
|
+
* Preserves parent heading breadcrumbs for every content block.
|
|
8
|
+
* Output: `[Session 142 > Traps > Next.js Caching] We found that...`
|
|
9
|
+
*/
|
|
10
|
+
export declare class SessionLogChunker implements Chunker {
|
|
11
|
+
readonly strategy: ChunkStrategy;
|
|
12
|
+
chunk(content: string, filePath: string, type: ContentType): Chunk[];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=session-log-chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-log-chunker.d.ts","sourceRoot":"","sources":["../../src/chunkers/session-log-chunker.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IAC/C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAiB;IAEjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE;CA8CrE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import remarkParse from 'remark-parse';
|
|
2
|
+
import { unified } from 'unified';
|
|
3
|
+
/**
|
|
4
|
+
* Session Log Chunker — the most critical chunker.
|
|
5
|
+
*
|
|
6
|
+
* Preserves parent heading breadcrumbs for every content block.
|
|
7
|
+
* Output: `[Session 142 > Traps > Next.js Caching] We found that...`
|
|
8
|
+
*/
|
|
9
|
+
export class SessionLogChunker {
|
|
10
|
+
strategy = 'session-log';
|
|
11
|
+
chunk(content, filePath, type) {
|
|
12
|
+
const tree = unified().use(remarkParse).parse(content);
|
|
13
|
+
const chunks = [];
|
|
14
|
+
// Heading breadcrumb stack: index = depth-1, value = heading text.
|
|
15
|
+
// When we encounter a heading of depth N, we clear all headings deeper than N.
|
|
16
|
+
const breadcrumbs = [];
|
|
17
|
+
for (const node of tree.children) {
|
|
18
|
+
if (node.type === 'heading') {
|
|
19
|
+
const heading = node;
|
|
20
|
+
const depth = heading.depth;
|
|
21
|
+
const text = extractPlainText(heading.children);
|
|
22
|
+
// Set this depth, truncate deeper levels
|
|
23
|
+
breadcrumbs[depth - 1] = text;
|
|
24
|
+
breadcrumbs.length = depth;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
// For any content node, emit a chunk with breadcrumb context
|
|
28
|
+
const text = nodeToText(node, content);
|
|
29
|
+
if (!text.trim())
|
|
30
|
+
continue;
|
|
31
|
+
const breadcrumbPath = breadcrumbs.filter(Boolean).join(' > ');
|
|
32
|
+
const contextPrefix = breadcrumbPath ? `[${breadcrumbPath}]` : `[${filePath}]`;
|
|
33
|
+
const label = breadcrumbPath || filePath;
|
|
34
|
+
const startLine = node.position?.start.line ?? 1;
|
|
35
|
+
const endLine = node.position?.end.line ?? startLine;
|
|
36
|
+
chunks.push({
|
|
37
|
+
content: text.trim(),
|
|
38
|
+
contextPrefix,
|
|
39
|
+
filePath,
|
|
40
|
+
type,
|
|
41
|
+
strategy: this.strategy,
|
|
42
|
+
label,
|
|
43
|
+
startLine,
|
|
44
|
+
endLine,
|
|
45
|
+
metadata: {},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return chunks;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Extract plain text from mdast phrasing content nodes. */
|
|
52
|
+
function extractPlainText(nodes) {
|
|
53
|
+
return nodes
|
|
54
|
+
.map((n) => {
|
|
55
|
+
if (n.type === 'text')
|
|
56
|
+
return n.value;
|
|
57
|
+
if ('children' in n)
|
|
58
|
+
return extractPlainText(n.children);
|
|
59
|
+
return '';
|
|
60
|
+
})
|
|
61
|
+
.join('');
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Convert an mdast content node back to its original text
|
|
65
|
+
* using the source position to slice the original content.
|
|
66
|
+
*/
|
|
67
|
+
function nodeToText(node, source) {
|
|
68
|
+
if (node.position) {
|
|
69
|
+
const lines = source.split('\n');
|
|
70
|
+
const startIdx = node.position.start.line - 1;
|
|
71
|
+
const endIdx = node.position.end.line;
|
|
72
|
+
return lines.slice(startIdx, endIdx).join('\n');
|
|
73
|
+
}
|
|
74
|
+
if ('value' in node && typeof node.value === 'string')
|
|
75
|
+
return node.value;
|
|
76
|
+
return '';
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=session-log-chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-log-chunker.js","sourceRoot":"","sources":["../../src/chunkers/session-log-chunker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChunkStrategy, ContentType } from '../config-schema.js';
|
|
2
|
+
import type { Chunk } from '../types.js';
|
|
3
|
+
import type { Chunker } from './chunker.js';
|
|
4
|
+
/**
|
|
5
|
+
* Test File Chunker.
|
|
6
|
+
*
|
|
7
|
+
* Chunks by describe/it/test blocks.
|
|
8
|
+
* A `describe` block includes its nested `it` calls.
|
|
9
|
+
* Top-level `it`/`test` calls become their own chunks.
|
|
10
|
+
*/
|
|
11
|
+
export declare class TestFileChunker implements Chunker {
|
|
12
|
+
readonly strategy: ChunkStrategy;
|
|
13
|
+
chunk(content: string, filePath: string, type: ContentType): Chunk[];
|
|
14
|
+
private getCallName;
|
|
15
|
+
private extractTestLabel;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=test-file-chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-file-chunker.d.ts","sourceRoot":"","sources":["../../src/chunkers/test-file-chunker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAI5C;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,OAAO;IAC7C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAe;IAE/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE;IA2CpE,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,gBAAgB;CAUzB"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
const TEST_FUNCTIONS = new Set(['describe', 'it', 'test']);
|
|
3
|
+
/**
|
|
4
|
+
* Test File Chunker.
|
|
5
|
+
*
|
|
6
|
+
* Chunks by describe/it/test blocks.
|
|
7
|
+
* A `describe` block includes its nested `it` calls.
|
|
8
|
+
* Top-level `it`/`test` calls become their own chunks.
|
|
9
|
+
*/
|
|
10
|
+
export class TestFileChunker {
|
|
11
|
+
strategy = 'test-file';
|
|
12
|
+
chunk(content, filePath, type) {
|
|
13
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
14
|
+
const chunks = [];
|
|
15
|
+
const lines = content.split('\n');
|
|
16
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
17
|
+
if (!ts.isExpressionStatement(node))
|
|
18
|
+
return;
|
|
19
|
+
if (!ts.isCallExpression(node.expression))
|
|
20
|
+
return;
|
|
21
|
+
const callName = this.getCallName(node.expression);
|
|
22
|
+
if (!callName || !TEST_FUNCTIONS.has(callName))
|
|
23
|
+
return;
|
|
24
|
+
const label = this.extractTestLabel(node.expression);
|
|
25
|
+
const startPos = node.getStart(sourceFile);
|
|
26
|
+
const endPos = node.getEnd();
|
|
27
|
+
const startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line + 1;
|
|
28
|
+
const endLine = sourceFile.getLineAndCharacterOfPosition(endPos).line + 1;
|
|
29
|
+
const text = lines.slice(startLine - 1, endLine).join('\n');
|
|
30
|
+
chunks.push({
|
|
31
|
+
content: text,
|
|
32
|
+
contextPrefix: `File: ${filePath} | Test: ${label}`,
|
|
33
|
+
filePath,
|
|
34
|
+
type,
|
|
35
|
+
strategy: this.strategy,
|
|
36
|
+
label: `${callName}: ${label}`,
|
|
37
|
+
startLine,
|
|
38
|
+
endLine,
|
|
39
|
+
metadata: { testType: callName },
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
return chunks;
|
|
43
|
+
}
|
|
44
|
+
getCallName(expr) {
|
|
45
|
+
if (ts.isIdentifier(expr.expression)) {
|
|
46
|
+
return expr.expression.text;
|
|
47
|
+
}
|
|
48
|
+
// Handle describe.skip, it.skip, etc.
|
|
49
|
+
if (ts.isPropertyAccessExpression(expr.expression) &&
|
|
50
|
+
ts.isIdentifier(expr.expression.expression)) {
|
|
51
|
+
return expr.expression.expression.text;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
extractTestLabel(expr) {
|
|
56
|
+
const firstArg = expr.arguments[0];
|
|
57
|
+
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
58
|
+
return firstArg.text;
|
|
59
|
+
}
|
|
60
|
+
if (firstArg && ts.isNoSubstitutionTemplateLiteral(firstArg)) {
|
|
61
|
+
return firstArg.text;
|
|
62
|
+
}
|
|
63
|
+
return 'unnamed';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=test-file-chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-file-chunker.js","sourceRoot":"","sources":["../../src/chunkers/test-file-chunker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChunkStrategy, ContentType } from '../config-schema.js';
|
|
2
|
+
import type { Chunk } from '../types.js';
|
|
3
|
+
import type { Chunker } from './chunker.js';
|
|
4
|
+
/**
|
|
5
|
+
* TypeScript AST Chunker.
|
|
6
|
+
*
|
|
7
|
+
* Chunks by function, class, interface, type alias, enum declarations.
|
|
8
|
+
* Detects React components (PascalCase) and hooks (use* prefix).
|
|
9
|
+
* Context: `File: <path> | Context: The '<name>' <kind>`
|
|
10
|
+
*/
|
|
11
|
+
export declare class TypeScriptChunker implements Chunker {
|
|
12
|
+
readonly strategy: ChunkStrategy;
|
|
13
|
+
chunk(content: string, filePath: string, type: ContentType): Chunk[];
|
|
14
|
+
private extractDeclaration;
|
|
15
|
+
private classifyFunction;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=typescript-chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-chunker.d.ts","sourceRoot":"","sources":["../../src/chunkers/typescript-chunker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;;;GAMG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IAC/C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAoB;IAEpD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE;IA+BpE,OAAO,CAAC,kBAAkB;IA4D1B,OAAO,CAAC,gBAAgB;CASzB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* TypeScript AST Chunker.
|
|
4
|
+
*
|
|
5
|
+
* Chunks by function, class, interface, type alias, enum declarations.
|
|
6
|
+
* Detects React components (PascalCase) and hooks (use* prefix).
|
|
7
|
+
* Context: `File: <path> | Context: The '<name>' <kind>`
|
|
8
|
+
*/
|
|
9
|
+
export class TypeScriptChunker {
|
|
10
|
+
strategy = 'typescript-ast';
|
|
11
|
+
chunk(content, filePath, type) {
|
|
12
|
+
const scriptKind = filePath.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
|
|
13
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, scriptKind);
|
|
14
|
+
const chunks = [];
|
|
15
|
+
const lines = content.split('\n');
|
|
16
|
+
const visit = (node, depth) => {
|
|
17
|
+
// Only chunk top-level declarations (class methods stay inside the class chunk)
|
|
18
|
+
if (depth > 1)
|
|
19
|
+
return;
|
|
20
|
+
const extracted = this.extractDeclaration(node, sourceFile, lines, filePath, type);
|
|
21
|
+
if (extracted) {
|
|
22
|
+
chunks.push(extracted);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
ts.forEachChild(node, (child) => visit(child, depth + 1));
|
|
26
|
+
};
|
|
27
|
+
ts.forEachChild(sourceFile, (child) => visit(child, 0));
|
|
28
|
+
return chunks;
|
|
29
|
+
}
|
|
30
|
+
extractDeclaration(node, sourceFile, lines, filePath, contentType) {
|
|
31
|
+
let name = null;
|
|
32
|
+
let kind = null;
|
|
33
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
34
|
+
name = node.name.text;
|
|
35
|
+
kind = this.classifyFunction(name);
|
|
36
|
+
}
|
|
37
|
+
else if (ts.isClassDeclaration(node) && node.name) {
|
|
38
|
+
name = node.name.text;
|
|
39
|
+
kind = 'class';
|
|
40
|
+
}
|
|
41
|
+
else if (ts.isInterfaceDeclaration(node)) {
|
|
42
|
+
name = node.name.text;
|
|
43
|
+
kind = 'interface';
|
|
44
|
+
}
|
|
45
|
+
else if (ts.isTypeAliasDeclaration(node)) {
|
|
46
|
+
name = node.name.text;
|
|
47
|
+
kind = 'type alias';
|
|
48
|
+
}
|
|
49
|
+
else if (ts.isEnumDeclaration(node)) {
|
|
50
|
+
name = node.name.text;
|
|
51
|
+
kind = 'enum';
|
|
52
|
+
}
|
|
53
|
+
else if (ts.isVariableStatement(node)) {
|
|
54
|
+
// Handle: export const MyComponent = () => { ... }
|
|
55
|
+
for (const decl of node.declarationList.declarations) {
|
|
56
|
+
if (ts.isIdentifier(decl.name) && decl.initializer) {
|
|
57
|
+
if (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer)) {
|
|
58
|
+
name = decl.name.text;
|
|
59
|
+
kind = this.classifyFunction(name);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!name || !kind)
|
|
65
|
+
return null;
|
|
66
|
+
const startPos = node.getStart(sourceFile);
|
|
67
|
+
const endPos = node.getEnd();
|
|
68
|
+
const startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line + 1;
|
|
69
|
+
const endLine = sourceFile.getLineAndCharacterOfPosition(endPos).line + 1;
|
|
70
|
+
const text = lines.slice(startLine - 1, endLine).join('\n');
|
|
71
|
+
const contextPrefix = `File: ${filePath} | Context: The '${name}' ${kind}`;
|
|
72
|
+
return {
|
|
73
|
+
content: text,
|
|
74
|
+
contextPrefix,
|
|
75
|
+
filePath,
|
|
76
|
+
type: contentType,
|
|
77
|
+
strategy: this.strategy,
|
|
78
|
+
label: `${kind}: ${name}`,
|
|
79
|
+
startLine,
|
|
80
|
+
endLine,
|
|
81
|
+
metadata: { name, kind },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
classifyFunction(name) {
|
|
85
|
+
if (name.startsWith('use') && name[3]?.toUpperCase() === name[3]) {
|
|
86
|
+
return 'hook';
|
|
87
|
+
}
|
|
88
|
+
if (name[0]?.toUpperCase() === name[0]) {
|
|
89
|
+
return 'component';
|
|
90
|
+
}
|
|
91
|
+
return 'function';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=typescript-chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-chunker.js","sourceRoot":"","sources":["../../src/chunkers/typescript-chunker.ts"],"names":[],"mappings":"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"}
|