@eduardo-afonso/codebase-intelligence 0.1.0 → 2.0.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.
Files changed (108) hide show
  1. package/README.md +82 -7
  2. package/README.pt-BR.md +84 -8
  3. package/dist/ai/CodebaseWithAI.d.ts +91 -0
  4. package/dist/ai/CodebaseWithAI.d.ts.map +1 -0
  5. package/dist/ai/CodebaseWithAI.js +149 -0
  6. package/dist/ai/CodebaseWithAI.js.map +1 -0
  7. package/dist/ai/RAGPipeline.d.ts +66 -0
  8. package/dist/ai/RAGPipeline.d.ts.map +1 -0
  9. package/dist/ai/RAGPipeline.js +102 -0
  10. package/dist/ai/RAGPipeline.js.map +1 -0
  11. package/dist/ai/index.d.ts +6 -0
  12. package/dist/ai/index.d.ts.map +1 -0
  13. package/dist/ai/index.js +5 -0
  14. package/dist/ai/index.js.map +1 -0
  15. package/dist/ai/providers/NoopAIProvider.d.ts +23 -0
  16. package/dist/ai/providers/NoopAIProvider.d.ts.map +1 -0
  17. package/dist/ai/providers/NoopAIProvider.js +24 -0
  18. package/dist/ai/providers/NoopAIProvider.js.map +1 -0
  19. package/dist/cli/index.js +168 -8
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/context/ContextEngine.d.ts +54 -0
  22. package/dist/context/ContextEngine.d.ts.map +1 -0
  23. package/dist/context/ContextEngine.js +179 -0
  24. package/dist/context/ContextEngine.js.map +1 -0
  25. package/dist/context/FileContextBuilder.d.ts +49 -0
  26. package/dist/context/FileContextBuilder.d.ts.map +1 -0
  27. package/dist/context/FileContextBuilder.js +124 -0
  28. package/dist/context/FileContextBuilder.js.map +1 -0
  29. package/dist/context/SemanticChunker.d.ts +105 -0
  30. package/dist/context/SemanticChunker.d.ts.map +1 -0
  31. package/dist/context/SemanticChunker.js +293 -0
  32. package/dist/context/SemanticChunker.js.map +1 -0
  33. package/dist/context/SignatureExtractor.d.ts +49 -0
  34. package/dist/context/SignatureExtractor.d.ts.map +1 -0
  35. package/dist/context/SignatureExtractor.js +167 -0
  36. package/dist/context/SignatureExtractor.js.map +1 -0
  37. package/dist/context/interfaces.d.ts +149 -0
  38. package/dist/context/interfaces.d.ts.map +1 -0
  39. package/dist/context/interfaces.js +13 -0
  40. package/dist/context/interfaces.js.map +1 -0
  41. package/dist/context/strategies/ContextBuildStrategy.d.ts +25 -0
  42. package/dist/context/strategies/ContextBuildStrategy.d.ts.map +1 -0
  43. package/dist/context/strategies/ContextBuildStrategy.js +3 -0
  44. package/dist/context/strategies/ContextBuildStrategy.js.map +1 -0
  45. package/dist/context/strategies/DeepStrategy.d.ts +18 -0
  46. package/dist/context/strategies/DeepStrategy.d.ts.map +1 -0
  47. package/dist/context/strategies/DeepStrategy.js +19 -0
  48. package/dist/context/strategies/DeepStrategy.js.map +1 -0
  49. package/dist/context/strategies/ShallowStrategy.d.ts +15 -0
  50. package/dist/context/strategies/ShallowStrategy.d.ts.map +1 -0
  51. package/dist/context/strategies/ShallowStrategy.js +15 -0
  52. package/dist/context/strategies/ShallowStrategy.js.map +1 -0
  53. package/dist/context/strategies/SignatureStrategy.d.ts +20 -0
  54. package/dist/context/strategies/SignatureStrategy.d.ts.map +1 -0
  55. package/dist/context/strategies/SignatureStrategy.js +59 -0
  56. package/dist/context/strategies/SignatureStrategy.js.map +1 -0
  57. package/dist/context/strategies/index.d.ts +5 -0
  58. package/dist/context/strategies/index.d.ts.map +1 -0
  59. package/dist/context/strategies/index.js +4 -0
  60. package/dist/context/strategies/index.js.map +1 -0
  61. package/dist/context/types.d.ts +136 -0
  62. package/dist/context/types.d.ts.map +1 -0
  63. package/dist/context/types.js +8 -0
  64. package/dist/context/types.js.map +1 -0
  65. package/dist/core/Codebase.d.ts +50 -0
  66. package/dist/core/Codebase.d.ts.map +1 -1
  67. package/dist/core/Codebase.js +104 -0
  68. package/dist/core/Codebase.js.map +1 -1
  69. package/dist/diff/ChangeSetImpactAnalyzer.d.ts +19 -0
  70. package/dist/diff/ChangeSetImpactAnalyzer.d.ts.map +1 -0
  71. package/dist/diff/ChangeSetImpactAnalyzer.js +121 -0
  72. package/dist/diff/ChangeSetImpactAnalyzer.js.map +1 -0
  73. package/dist/diff/GitChangeSetProvider.d.ts +86 -0
  74. package/dist/diff/GitChangeSetProvider.d.ts.map +1 -0
  75. package/dist/diff/GitChangeSetProvider.js +297 -0
  76. package/dist/diff/GitChangeSetProvider.js.map +1 -0
  77. package/dist/diff/errors.d.ts +48 -0
  78. package/dist/diff/errors.d.ts.map +1 -0
  79. package/dist/diff/errors.js +70 -0
  80. package/dist/diff/errors.js.map +1 -0
  81. package/dist/diff/types.d.ts +159 -0
  82. package/dist/diff/types.d.ts.map +1 -0
  83. package/dist/diff/types.js +8 -0
  84. package/dist/diff/types.js.map +1 -0
  85. package/dist/explorer/SnapshotBuilder.d.ts +22 -0
  86. package/dist/explorer/SnapshotBuilder.d.ts.map +1 -0
  87. package/dist/explorer/SnapshotBuilder.js +225 -0
  88. package/dist/explorer/SnapshotBuilder.js.map +1 -0
  89. package/dist/explorer/types.d.ts +88 -0
  90. package/dist/explorer/types.d.ts.map +1 -0
  91. package/dist/explorer/types.js +12 -0
  92. package/dist/explorer/types.js.map +1 -0
  93. package/dist/explorer/ui/App.d.ts +3 -0
  94. package/dist/explorer/ui/App.d.ts.map +1 -0
  95. package/dist/explorer/ui/App.js +43 -0
  96. package/dist/explorer/ui/App.js.map +1 -0
  97. package/dist/explorer/ui/main.d.ts +2 -0
  98. package/dist/explorer/ui/main.d.ts.map +1 -0
  99. package/dist/explorer/ui/main.js +8 -0
  100. package/dist/explorer/ui/main.js.map +1 -0
  101. package/dist/index.d.ts +17 -0
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +16 -0
  104. package/dist/index.js.map +1 -1
  105. package/dist/ui/assets/index-D4w3JVrv.css +1 -0
  106. package/dist/ui/assets/index-DBRKE5qL.js +52 -0
  107. package/dist/ui/index.html +13 -0
  108. package/package.json +50 -50
package/README.md CHANGED
@@ -16,6 +16,8 @@ Codebase Intelligence acts as a foundational "Knowledge Graph" for your code. It
16
16
  - **Dependency Graph**: Builds a directed graph of imports, `extends`, and `implements`.
17
17
  - **Code Search**: Lexical and structural search across files and symbols.
18
18
  - **Impact Analysis**: Understand the direct and indirect consequences of modifying any given file, including related test files.
19
+ - **Diff Impact Analysis**: Given Git changes (a branch, staged files, uncommitted edits), answer *"what does this set of changes affect?"* — conservatively, at file granularity, without inventing relationships.
20
+ - **Context Engine**: Build token-budgeted, LLM-ready context payloads using three strategies (shallow, signature, deep).
19
21
  - **CLI Included**: Run analyses and queries directly from your terminal.
20
22
 
21
23
  ---
@@ -23,7 +25,7 @@ Codebase Intelligence acts as a foundational "Knowledge Graph" for your code. It
23
25
  ## Installation
24
26
 
25
27
  ```bash
26
- npm install codebase-intelligence
28
+ npm i @eduardo-afonso/codebase-intelligence
27
29
  ```
28
30
 
29
31
  *(Note: Currently in MVP phase. Ensure your project has TypeScript setup to use properly).*
@@ -86,6 +88,51 @@ Returns files that directly depend on the target file.
86
88
  ### `codebase.impact(file: string): ImpactResult`
87
89
  Returns `{ direct: string[], indirect: string[], tests: string[] }`, revealing the full blast radius of a change to the given file.
88
90
 
91
+ ### `codebase.impactOfFiles(paths: string[]): ChangeSetImpact`
92
+ Pure, synchronous impact analysis without querying Git. Treats all given relative paths as `modified` and resolves their dependents from the graph.
93
+
94
+ ```typescript
95
+ const impact = codebase.impactOfFiles(['src/auth/AuthService.ts']);
96
+ console.log(impact.direct); // direct importers
97
+ console.log(impact.indirect); // transitive dependents
98
+ console.log(impact.tests); // test files (by naming convention)
99
+ console.log(impact.globalChanges); // config files that affect everything
100
+ console.log(impact.unanalyzable); // files that couldn't be traced + why
101
+ ```
102
+
103
+ ### `codebase.impactOfChanges(options?, provider?): Promise<ChangeSetImpact>`
104
+ Queries a `ChangeSetProvider` (Git by default) to determine which files changed, then maps that to a `ChangeSetImpact`.
105
+
106
+ ```typescript
107
+ // Changes introduced by the current branch vs main:
108
+ const impact = await codebase.impactOfChanges({ since: 'main' });
109
+
110
+ // Only staged changes:
111
+ const staged = await codebase.impactOfChanges({ staged: true });
112
+
113
+ // All uncommitted changes (including untracked files):
114
+ const uncommitted = await codebase.impactOfChanges();
115
+
116
+ // Custom provider (e.g. GitHub PR API, test stub):
117
+ const impact = await codebase.impactOfChanges({}, myCustomProvider);
118
+ ```
119
+
120
+ **`ChangeSetImpact` shape:**
121
+ ```typescript
122
+ {
123
+ changed: FileChange[]; // raw list from the provider
124
+ direct: string[]; // files that directly import a changed file
125
+ indirect: string[]; // transitive dependents (minus direct)
126
+ tests: string[]; // test files by naming convention
127
+ globalChanges: string[]; // e.g. package.json, tsconfig.json
128
+ unanalyzable: { path, reason }[]; // files that couldn't be traced
129
+ unresolvedDependencies: string[]; // unresolvable import specifiers
130
+ metadata: { granularity: 'file'; base?: string; head?: string };
131
+ }
132
+ ```
133
+
134
+ > ⚠️ **Granularity note**: the analysis operates at **file granularity**. A one-line change marks *all* dependents of that file as potentially affected. The result is a conservative upper bound.
135
+
89
136
  ---
90
137
 
91
138
  ## CLI Reference
@@ -105,8 +152,36 @@ npx codebase-intelligence dependencies "src/auth/AuthService.ts" .
105
152
  # View what depends on a file
106
153
  npx codebase-intelligence dependents "src/auth/AuthService.ts" .
107
154
 
108
- # View the full impact of a file
109
- npx codebase-intelligence impact "src/auth/AuthService.ts" .
155
+ # ── Impact Analysis ─────────────────────────────────────────────────────
156
+
157
+ # Classic file-mode: impact of a single file
158
+ npx codebase-intelligence impact src/auth/AuthService.ts .
159
+
160
+ # Diff mode: what does changing since main affect? (merge-base comparison)
161
+ npx codebase-intelligence impact . --since main
162
+
163
+ # Diff mode: only staged changes
164
+ npx codebase-intelligence impact . --staged
165
+
166
+ # Diff mode: all uncommitted changes + untracked files
167
+ npx codebase-intelligence impact . --uncommitted
168
+
169
+ # Output as JSON (clean on stdout, suitable for piping)
170
+ npx codebase-intelligence impact . --since main --format json
171
+
172
+ # Print only related test paths — useful in CI scripts
173
+ npx codebase-intelligence impact . --since main --tests-only
174
+
175
+ # ── Context & Chunking ───────────────────────────────────────────────────
176
+
177
+ # Generate an LLM-ready context payload for a file (including dependencies)
178
+ npx codebase-intelligence context "src/auth/AuthService.ts" --strategy signature .
179
+
180
+ # Generate semantic chunks for the codebase
181
+ npx codebase-intelligence chunks . --max-tokens 512
182
+
183
+ # Estimate token usage for the entire codebase
184
+ npx codebase-intelligence tokens .
110
185
  ```
111
186
 
112
187
  ---
@@ -125,12 +200,12 @@ For deeper architectural details, see [docs/architecture.md](docs/architecture.m
125
200
 
126
201
  ## Roadmap
127
202
 
128
- The current version (MVP) establishes the deterministic structural analysis of a codebase. Future versions will introduce:
203
+ The current version establishes the deterministic structural analysis of a codebase, includes the **Context Engine** for semantic chunking and RAG pipelines, and now features **Diff Impact Analysis** for Git change sets. Future versions will introduce:
129
204
 
130
- - **AI Adapters**: Interfaces to connect external LLMs (OpenAI, Anthropic, Gemini, Ollama).
131
- - **RAG & Embeddings Pipeline**: Automatic chunking and vector storage integrations for semantic code search.
132
- - **Context Engine**: Tools to dynamically generate context payloads for LLMs based on the dependency graph.
205
+ - **AI Adapters**: Concrete implementations to connect external LLMs (OpenAI, Anthropic, Gemini, Ollama) and Vector Stores (Qdrant, Chroma).
133
206
  - **Multi-language Support**: Expanding the `ParserRegistry` to handle Python, Go, and C#.
207
+ - **Symbol-level Granularity**: Narrowing impact analysis from file-level to the specific changed symbols.
208
+ - **Incremental Indexing**: Avoid full re-analysis on every run by detecting changed files from the index cache.
134
209
 
135
210
  ---
136
211
 
package/README.pt-BR.md CHANGED
@@ -16,6 +16,8 @@ O Codebase Intelligence funciona como um "Grafo de Conhecimento" fundamental par
16
16
  - **Grafo de Dependências**: Constrói um grafo direcionado de imports, `extends` e `implements`.
17
17
  - **Busca de Código**: Busca léxica e estrutural em arquivos e símbolos.
18
18
  - **Análise de Impacto**: Entenda as consequências diretas e indiretas de modificar qualquer arquivo, incluindo arquivos de teste relacionados.
19
+ - **Análise de Impacto de Diferenças (Diff Impact)**: Dado um conjunto de alterações no Git (um branch, arquivos em stage, edições não commitadas), descubra *"o que este conjunto de mudanças afeta?"* — de forma conservadora, na granularidade do arquivo, sem inventar relações.
20
+ - **Context Engine**: Crie payloads de contexto prontos para LLMs, com controle de tokens, usando três estratégias (shallow, signature, deep).
19
21
  - **CLI Incluída**: Execute análises e consultas diretamente pelo terminal.
20
22
 
21
23
  ---
@@ -23,7 +25,7 @@ O Codebase Intelligence funciona como um "Grafo de Conhecimento" fundamental par
23
25
  ## Instalação
24
26
 
25
27
  ```bash
26
- npm install codebase-intelligence
28
+ npm i @eduardo-afonso/codebase-intelligence
27
29
  ```
28
30
 
29
31
  *(Nota: Atualmente em fase de MVP. Certifique-se de que seu projeto tenha o TypeScript configurado para uso adequado).*
@@ -86,6 +88,52 @@ Retorna os arquivos que dependem diretamente do arquivo informado.
86
88
  ### `codebase.impact(file: string): ImpactResult`
87
89
  Retorna `{ direct: string[], indirect: string[], tests: string[] }`, revelando o raio de impacto completo de uma alteração no arquivo informado.
88
90
 
91
+ ### `codebase.impactOfFiles(paths: string[]): ChangeSetImpact`
92
+ Análise de impacto pura e síncrona sem consultar o Git. Trata todos os caminhos relativos fornecidos como `modificados` e resolve as suas dependências através do grafo.
93
+
94
+ ```typescript
95
+ // O que é afetado se alterar utils.ts?
96
+ const impact = codebase.impactOfFiles(['src/utils.ts']);
97
+ console.log(impact.direct); // importadores diretos
98
+ console.log(impact.indirect); // dependentes transitivos
99
+ console.log(impact.tests); // arquivos de teste (por convenção)
100
+ console.log(impact.globalChanges); // arquivos globais (afetam tudo)
101
+ console.log(impact.unanalyzable); // arquivos não indexados e porquê
102
+ ```
103
+
104
+ ### `codebase.impactOfChanges(options?, provider?): Promise<ChangeSetImpact>`
105
+ Consulta um `ChangeSetProvider` (Git por defeito) para determinar quais os arquivos alterados, mapeando-os para um `ChangeSetImpact`.
106
+
107
+ ```typescript
108
+ // Alterações introduzidas pela branch atual vs main:
109
+ const impact = await codebase.impactOfChanges({ since: 'main' });
110
+
111
+ // Apenas arquivos em stage:
112
+ const staged = await codebase.impactOfChanges({ staged: true });
113
+
114
+ // Todas as alterações não commitadas (incluindo arquivos untracked):
115
+ const uncommitted = await codebase.impactOfChanges();
116
+
117
+ // Provider personalizado (ex: API de PR do GitHub, mock de teste):
118
+ const impact = await codebase.impactOfChanges({}, meuProvider);
119
+ ```
120
+
121
+ **Formato de `ChangeSetImpact`:**
122
+ ```typescript
123
+ {
124
+ changed: FileChange[]; // lista bruta do provider
125
+ direct: string[]; // arquivos que importam um arquivo alterado
126
+ indirect: string[]; // dependentes transitivos (excluindo direct)
127
+ tests: string[]; // arquivos de teste por convenção de nomes
128
+ globalChanges: string[]; // ex: package.json, tsconfig.json
129
+ unanalyzable: { path, reason }[]; // arquivos não rastreáveis
130
+ unresolvedDependencies: string[]; // imports impossíveis de resolver
131
+ metadata: { granularity: 'file'; base?: string; head?: string };
132
+ }
133
+ ```
134
+
135
+ > ⚠️ **Nota sobre granularidade**: a análise opera na **granularidade de arquivo**. Uma alteração de uma linha marca *todos* os dependentes desse arquivo como potencialmente afetados. O resultado é um limite superior conservador.
136
+
89
137
  ---
90
138
 
91
139
  ## Referência da CLI
@@ -105,8 +153,36 @@ npx codebase-intelligence dependencies "src/auth/AuthService.ts" .
105
153
  # Exibe o que depende de um arquivo
106
154
  npx codebase-intelligence dependents "src/auth/AuthService.ts" .
107
155
 
108
- # Exibe o impacto completo de um arquivo
109
- npx codebase-intelligence impact "src/auth/AuthService.ts" .
156
+ # ── Análise de Impacto ──────────────────────────────────────────────────
157
+
158
+ # Modo de arquivo clássico: impacto de um único arquivo
159
+ npx codebase-intelligence impact src/auth/AuthService.ts .
160
+
161
+ # Modo Diff: o que afetam as mudanças desde a branch main? (comparação merge-base)
162
+ npx codebase-intelligence impact . --since main
163
+
164
+ # Modo Diff: apenas arquivos em stage
165
+ npx codebase-intelligence impact . --staged
166
+
167
+ # Modo Diff: todas as alterações não commitadas + arquivos untracked
168
+ npx codebase-intelligence impact . --uncommitted
169
+
170
+ # Saída em JSON (limpo em stdout, ideal para scripts)
171
+ npx codebase-intelligence impact . --since main --format json
172
+
173
+ # Imprime apenas caminhos de testes relacionados — útil em CI
174
+ npx codebase-intelligence impact . --since main --tests-only
175
+
176
+ # ── Context Engine & Chunking ────────────────────────────────────────────
177
+
178
+ # Gera um payload de contexto pronto para LLMs para um arquivo (incluindo dependências)
179
+ npx codebase-intelligence context "src/auth/AuthService.ts" --strategy signature .
180
+
181
+ # Gera chunks semânticos para a base de código
182
+ npx codebase-intelligence chunks . --max-tokens 512
183
+
184
+ # Estima o uso de tokens de toda a base de código
185
+ npx codebase-intelligence tokens .
110
186
  ```
111
187
 
112
188
  ---
@@ -125,12 +201,12 @@ Para detalhes arquiteturais mais profundos, veja [docs/architecture.md](docs/arc
125
201
 
126
202
  ## Roadmap
127
203
 
128
- A versão atual (MVP) estabelece a análise estrutural determinística de uma base de código. Versões futuras irão introduzir:
204
+ A versão atual estabelece a análise estrutural determinística de uma base de código, inclui o **Context Engine** para chunking semântico e pipelines de RAG, e agora inclui **Análise de Impacto de Diferenças (Diff Impact)** para as alterações no Git. Versões futuras irão introduzir:
129
205
 
130
- - **Adaptadores de IA**: Interfaces para conectar LLMs externos (OpenAI, Anthropic, Gemini, Ollama).
131
- - **Pipeline de RAG e Embeddings**: Chunking automático e integrações de armazenamento vetorial para busca semântica de código.
132
- - **Context Engine**: Ferramentas para gerar dinamicamente payloads de contexto para LLMs com base no grafo de dependências.
206
+ - **Adaptadores de IA**: Implementações concretas para conectar LLMs externos (OpenAI, Anthropic, Gemini, Ollama) e Vector Stores (Qdrant, Chroma).
133
207
  - **Suporte Multi-linguagem**: Expansão do `ParserRegistry` para suportar Python, Go e C#.
208
+ - **Granularidade a nível de Símbolo**: Reduzindo a análise de impacto ao nível do arquivo para os símbolos especificamente alterados.
209
+ - **Indexação Incremental**: Evita a re-análise completa a cada execução detetando arquivos alterados da cache.
134
210
 
135
211
  ---
136
212
 
@@ -144,4 +220,4 @@ Contribuições são bem-vindas. Por favor, certifique-se de que você:
144
220
 
145
221
  ## Licença
146
222
 
147
- Licença ISC. Veja o arquivo `LICENSE` para mais detalhes.
223
+ Licença ISC. Veja o arquivo `LICENSE` para mais detalhes.
@@ -0,0 +1,91 @@
1
+ import type { AIProvider } from '../context/interfaces.js';
2
+ import type { ContextOptions, LLMContextPayload } from '../context/types.js';
3
+ import type { Codebase } from '../core/Codebase.js';
4
+ /** Options accepted by `CodebaseWithAI.explain()`. */
5
+ export interface ExplainOptions extends ContextOptions {
6
+ /**
7
+ * Optional instruction appended to the system prompt.
8
+ * Use to tailor the explanation style, e.g. `'Focus on security implications'`.
9
+ */
10
+ instruction?: string;
11
+ }
12
+ /** Options accepted by `CodebaseWithAI.ask()`. */
13
+ export interface AskOptions {
14
+ /**
15
+ * Maximum number of top search results to include as context.
16
+ * @default 3
17
+ */
18
+ topK?: number;
19
+ /**
20
+ * Context strategy applied when building each file's payload.
21
+ * @default 'signature'
22
+ */
23
+ strategy?: ContextOptions['strategy'];
24
+ /**
25
+ * Token budget for each individual context payload.
26
+ * @default 4000
27
+ */
28
+ maxTokens?: number;
29
+ }
30
+ /**
31
+ * Composes a `Codebase` with an `AIProvider` to expose high-level AI APIs.
32
+ *
33
+ * Consumers obtain an instance via `codebase.withAI(provider)`:
34
+ * ```ts
35
+ * const cbWithAI = codebase.withAI(new OpenAIProvider());
36
+ *
37
+ * const explanation = await cbWithAI.explain('src/auth/AuthService.ts');
38
+ * const answer = await cbWithAI.ask('Como funciona a autenticação?');
39
+ * ```
40
+ *
41
+ * This class is intentionally thin: it delegates context-building to the
42
+ * `ContextEngine` and text-completion to the injected `AIProvider`.
43
+ * No LLM SDK is imported here.
44
+ */
45
+ export declare class CodebaseWithAI {
46
+ private readonly codebase;
47
+ private readonly provider;
48
+ constructor(codebase: Codebase, provider: AIProvider);
49
+ /**
50
+ * Generates a natural-language explanation of the given file.
51
+ *
52
+ * The implementation:
53
+ * 1. Builds an `LLMContextPayload` for the file using the specified strategy.
54
+ * 2. Serialises the nodes as a Markdown-fenced code block per node.
55
+ * 3. Constructs a system prompt that includes project metadata.
56
+ * 4. Calls `provider.complete(prompt, systemPrompt)` and returns the result.
57
+ *
58
+ * @param file - Absolute or codebase-relative path to the file to explain.
59
+ * @param options - Context and explanation options.
60
+ * @returns The provider's plain-text response, or `''` for stub providers.
61
+ */
62
+ explain(file: string, options?: ExplainOptions): Promise<string>;
63
+ /**
64
+ * Answers a free-text question about the codebase.
65
+ *
66
+ * The implementation:
67
+ * 1. Uses `codebase.search()` to find the most relevant files.
68
+ * 2. Builds context payloads for the top-K results.
69
+ * 3. Concatenates the serialised nodes into a single prompt.
70
+ * 4. Calls `provider.complete(prompt, systemPrompt)` and returns the result.
71
+ *
72
+ * @param question - Natural-language question about the codebase.
73
+ * @param options - Search and context options.
74
+ * @returns The provider's plain-text response, or `''` for stub providers.
75
+ */
76
+ ask(question: string, options?: AskOptions): Promise<string>;
77
+ /**
78
+ * Exposes the prompt that `explain()` would send to the provider.
79
+ * Useful for debugging, logging, or prompt tuning without incurring
80
+ * LLM cost.
81
+ */
82
+ buildExplainPayload(file: string, options?: ExplainOptions): Promise<{
83
+ prompt: string;
84
+ systemPrompt: string;
85
+ payload: LLMContextPayload;
86
+ }>;
87
+ private buildExplainPrompt;
88
+ private buildAskPrompt;
89
+ private buildSystemPrompt;
90
+ }
91
+ //# sourceMappingURL=CodebaseWithAI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodebaseWithAI.d.ts","sourceRoot":"","sources":["../../src/ai/CodebaseWithAI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,sDAAsD;AACtD,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAF3B,YACmB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,UAAU,EACnC;IAIJ;;;;;;;;;;;;OAYG;IACU,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAKhF;IAED;;;;;;;;;;;;OAYG;IACU,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA6B5E;IAED;;;;OAIG;IACU,mBAAmB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,iBAAiB,CAAA;KAAE,CAAC,CAO/E;IAID,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,iBAAiB;CAuB1B"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Composes a `Codebase` with an `AIProvider` to expose high-level AI APIs.
3
+ *
4
+ * Consumers obtain an instance via `codebase.withAI(provider)`:
5
+ * ```ts
6
+ * const cbWithAI = codebase.withAI(new OpenAIProvider());
7
+ *
8
+ * const explanation = await cbWithAI.explain('src/auth/AuthService.ts');
9
+ * const answer = await cbWithAI.ask('Como funciona a autenticação?');
10
+ * ```
11
+ *
12
+ * This class is intentionally thin: it delegates context-building to the
13
+ * `ContextEngine` and text-completion to the injected `AIProvider`.
14
+ * No LLM SDK is imported here.
15
+ */
16
+ export class CodebaseWithAI {
17
+ codebase;
18
+ provider;
19
+ constructor(codebase, provider) {
20
+ this.codebase = codebase;
21
+ this.provider = provider;
22
+ }
23
+ // ---- Public API -------------------------------------------------------
24
+ /**
25
+ * Generates a natural-language explanation of the given file.
26
+ *
27
+ * The implementation:
28
+ * 1. Builds an `LLMContextPayload` for the file using the specified strategy.
29
+ * 2. Serialises the nodes as a Markdown-fenced code block per node.
30
+ * 3. Constructs a system prompt that includes project metadata.
31
+ * 4. Calls `provider.complete(prompt, systemPrompt)` and returns the result.
32
+ *
33
+ * @param file - Absolute or codebase-relative path to the file to explain.
34
+ * @param options - Context and explanation options.
35
+ * @returns The provider's plain-text response, or `''` for stub providers.
36
+ */
37
+ async explain(file, options = {}) {
38
+ const payload = await this.codebase.context().forFile(file, options);
39
+ const prompt = this.buildExplainPrompt(payload);
40
+ const systemPrompt = this.buildSystemPrompt(options.instruction);
41
+ return this.provider.complete(prompt, systemPrompt);
42
+ }
43
+ /**
44
+ * Answers a free-text question about the codebase.
45
+ *
46
+ * The implementation:
47
+ * 1. Uses `codebase.search()` to find the most relevant files.
48
+ * 2. Builds context payloads for the top-K results.
49
+ * 3. Concatenates the serialised nodes into a single prompt.
50
+ * 4. Calls `provider.complete(prompt, systemPrompt)` and returns the result.
51
+ *
52
+ * @param question - Natural-language question about the codebase.
53
+ * @param options - Search and context options.
54
+ * @returns The provider's plain-text response, or `''` for stub providers.
55
+ */
56
+ async ask(question, options = {}) {
57
+ const { topK = 3, strategy = 'signature', maxTokens = 4_000 } = options;
58
+ const searchOpts = { limit: topK };
59
+ const results = this.codebase.search(question, searchOpts);
60
+ if (results.length === 0) {
61
+ const systemPrompt = this.buildSystemPrompt();
62
+ return this.provider.complete(`Question: ${question}\n\nNo relevant files were found in the codebase.`, systemPrompt);
63
+ }
64
+ const contextEngine = this.codebase.context();
65
+ const payloads = [];
66
+ for (const result of results) {
67
+ try {
68
+ const payload = await contextEngine.forFile(result.file, { strategy, maxTokens });
69
+ payloads.push(payload);
70
+ }
71
+ catch {
72
+ // Skip files that fail context building (e.g. not in index)
73
+ }
74
+ }
75
+ const prompt = this.buildAskPrompt(question, payloads);
76
+ const systemPrompt = this.buildSystemPrompt();
77
+ return this.provider.complete(prompt, systemPrompt);
78
+ }
79
+ /**
80
+ * Exposes the prompt that `explain()` would send to the provider.
81
+ * Useful for debugging, logging, or prompt tuning without incurring
82
+ * LLM cost.
83
+ */
84
+ async buildExplainPayload(file, options = {}) {
85
+ const payload = await this.codebase.context().forFile(file, options);
86
+ return {
87
+ prompt: this.buildExplainPrompt(payload),
88
+ systemPrompt: this.buildSystemPrompt(options.instruction),
89
+ payload,
90
+ };
91
+ }
92
+ // ---- Prompt builders --------------------------------------------------
93
+ buildExplainPrompt(payload) {
94
+ const sections = [
95
+ `# Explain: \`${payload.target}\``,
96
+ '',
97
+ `**Strategy**: ${payload.strategy} | **~${payload.totalTokenEstimate} tokens**`,
98
+ '',
99
+ ];
100
+ if (payload.metadata.directDependencies.length > 0) {
101
+ sections.push(`**Direct dependencies**: ${payload.metadata.directDependencies.join(', ')}`, '');
102
+ }
103
+ sections.push('## Source code\n');
104
+ for (const node of payload.nodes) {
105
+ const label = node.kind === 'file'
106
+ ? `File: ${node.relativePath}`
107
+ : `${node.kind}: ${node.symbolName ?? node.relativePath}`;
108
+ sections.push(`### ${label}\n`);
109
+ sections.push(`\`\`\`typescript\n${node.content}\n\`\`\`\n`);
110
+ }
111
+ sections.push('\n---\nPlease explain the code above clearly and concisely.');
112
+ return sections.join('\n');
113
+ }
114
+ buildAskPrompt(question, payloads) {
115
+ const sections = ['# Codebase Context\n'];
116
+ for (const payload of payloads) {
117
+ sections.push(`## File: \`${payload.target}\`\n`);
118
+ for (const node of payload.nodes) {
119
+ const label = node.kind === 'file'
120
+ ? node.relativePath
121
+ : `${node.kind}: ${node.symbolName ?? node.relativePath}`;
122
+ sections.push(`### ${label}\n`);
123
+ sections.push(`\`\`\`typescript\n${node.content}\n\`\`\`\n`);
124
+ }
125
+ }
126
+ sections.push(`\n---\n# Question\n\n${question}`);
127
+ return sections.join('\n');
128
+ }
129
+ buildSystemPrompt(extraInstruction) {
130
+ const projectInfo = this.codebase.projectInfo();
131
+ const parts = [
132
+ 'You are an expert software engineer analysing a codebase.',
133
+ ];
134
+ if (projectInfo) {
135
+ const langs = projectInfo.languages.join(', ');
136
+ const frameworks = projectInfo.frameworks.join(', ');
137
+ if (langs)
138
+ parts.push(`The project uses: ${langs}.`);
139
+ if (frameworks)
140
+ parts.push(`Frameworks detected: ${frameworks}.`);
141
+ }
142
+ parts.push('Answer precisely and concisely. Cite specific symbols, files, and line references when relevant.');
143
+ if (extraInstruction) {
144
+ parts.push(extraInstruction);
145
+ }
146
+ return parts.join(' ');
147
+ }
148
+ }
149
+ //# sourceMappingURL=CodebaseWithAI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodebaseWithAI.js","sourceRoot":"","sources":["../../src/ai/CodebaseWithAI.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { SemanticChunker, SemanticChunk } from '../context/SemanticChunker.js';
2
+ import type { EmbeddingProvider, VectorStore } from '../context/interfaces.js';
3
+ import type { Codebase } from '../core/Codebase.js';
4
+ /**
5
+ * Options for instantiating the RAG pipeline.
6
+ */
7
+ export interface RAGPipelineOptions {
8
+ /**
9
+ * Responsible for dividing codebase files into semantically meaningful
10
+ * text chunks before embedding.
11
+ */
12
+ chunker: SemanticChunker;
13
+ /**
14
+ * Converts text chunks into dense numeric vectors.
15
+ * This is provided by an external integration (e.g. Ollama, OpenAI).
16
+ */
17
+ embedder: EmbeddingProvider;
18
+ /**
19
+ * Storage layer for the embeddings and chunk metadata, used for
20
+ * fast similarity search. Provided by an external integration (e.g. Qdrant).
21
+ */
22
+ store: VectorStore;
23
+ }
24
+ /**
25
+ * Orchestrates the Retrieval-Augmented Generation (RAG) pipeline for a codebase.
26
+ *
27
+ * It coordinates the extraction of semantic chunks, their conversion to
28
+ * embeddings, and storage in a vector database for semantic search.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const pipeline = new RAGPipeline({
33
+ * chunker: new SemanticChunker(),
34
+ * embedder: new OllamaEmbeddingProvider({ model: 'nomic-embed-text' }),
35
+ * store: new QdrantVectorStore({ url: 'http://localhost:6333' }),
36
+ * });
37
+ *
38
+ * await pipeline.index(codebase);
39
+ * const results = await pipeline.search('authentication logic');
40
+ * ```
41
+ */
42
+ export declare class RAGPipeline {
43
+ private chunker;
44
+ private embedder;
45
+ private store;
46
+ constructor(options: RAGPipelineOptions);
47
+ /**
48
+ * Processes the entire codebase: generates semantic chunks, embeds them,
49
+ * and upserts the vectors and metadata into the vector store.
50
+ *
51
+ * @param codebase The fully analyzed codebase.
52
+ */
53
+ index(codebase: Codebase): Promise<void>;
54
+ /**
55
+ * Performs a semantic search over the indexed codebase.
56
+ *
57
+ * Embeds the query text and retrieves the closest matching chunks
58
+ * from the vector store.
59
+ *
60
+ * @param query The natural language search query.
61
+ * @param topK The maximum number of results to return. Default is 5.
62
+ * @returns The top matching semantic chunks.
63
+ */
64
+ search(query: string, topK?: number): Promise<SemanticChunk[]>;
65
+ }
66
+ //# sourceMappingURL=RAGPipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RAGPipeline.d.ts","sourceRoot":"","sources":["../../src/ai/RAGPipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;;OAGG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAC5B;;;OAGG;IACH,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,KAAK,CAAc;IAE3B,YAAY,OAAO,EAAE,kBAAkB,EAItC;IAED;;;;;OAKG;IACU,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCpD;IAED;;;;;;;;;OASG;IACU,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,MAAU,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA4B7E;CACF"}