diff --git a/gitnexus/src/core/embeddings/text-generator.ts b/gitnexus/src/core/embeddings/text-generator.ts index 318e7808f..059ee339d 100644 --- a/gitnexus/src/core/embeddings/text-generator.ts +++ b/gitnexus/src/core/embeddings/text-generator.ts @@ -102,6 +102,19 @@ const generateFunctionText = ( return `${header}\n\n${cleaned}`; }; +/** + * Generate embedding text for Constructor nodes + */ +const generateConstructorText = ( + node: EmbeddableNode, + codeBody: string, + config: Partial, +): string => { + const header = buildMetadataHeader(node, config); + const cleaned = cleanContent(codeBody); + return `${header}\n\n${cleaned}`; +}; + /** * Generate embedding text for Class nodes * Signature + properties + method name list only (no method bodies) @@ -225,6 +238,10 @@ export const generateEmbeddingText = ( return generateClassText(node, codeBody, config); } + if (node.label === 'Constructor') { + return generateConstructorText(node, codeBody, config); + } + if (node.label === 'Function' || node.label === 'Method') { return generateFunctionText(node, codeBody, config); } diff --git a/gitnexus/src/core/embeddings/types.ts b/gitnexus/src/core/embeddings/types.ts index 871ed2857..09b09f9fc 100644 --- a/gitnexus/src/core/embeddings/types.ts +++ b/gitnexus/src/core/embeddings/types.ts @@ -10,6 +10,7 @@ export const CHUNKABLE_LABELS = [ 'Function', 'Method', + 'Constructor', 'Class', 'Interface', 'Struct', diff --git a/gitnexus/test/unit/text-generator.test.ts b/gitnexus/test/unit/text-generator.test.ts index 30cd73988..af4a7a637 100644 --- a/gitnexus/test/unit/text-generator.test.ts +++ b/gitnexus/test/unit/text-generator.test.ts @@ -3,6 +3,7 @@ import { generateEmbeddingText, truncateDescription, } from '../../src/core/embeddings/text-generator.js'; +import { isChunkableLabel } from '../../src/core/embeddings/types.js'; import type { EmbeddableNode } from '../../src/core/embeddings/types.js'; const baseNode: EmbeddableNode = { @@ -89,6 +90,24 @@ describe('text-generator', () => { }); }); + describe('Constructor label', () => { + it('is recognized as chunkable', () => { + expect(isChunkableLabel('Constructor')).toBe(true); + }); + + it('is recognized as embeddable', () => { + const node: EmbeddableNode = { + ...baseNode, + label: 'Constructor', + name: 'constructor', + content: 'constructor(private service: ApiClient) {\n this.service = service;\n}', + }; + const text = generateEmbeddingText(node, node.content); + expect(text).toContain('Constructor: constructor'); + expect(text).toContain('this.service = service'); + }); + }); + describe('truncateDescription', () => { it('returns short text unchanged', () => { expect(truncateDescription('short text', 150)).toBe('short text');