@git.zone/tsdoc 1.6.0 → 1.7.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.
@@ -62,6 +62,8 @@ export interface IContextConfig {
62
62
  prioritization?: IPrioritizationWeights;
63
63
  /** Tier configuration for adaptive trimming */
64
64
  tiers?: ITierConfig;
65
+ /** Iterative context building configuration */
66
+ iterative?: IIterativeConfig;
65
67
  }
66
68
  /**
67
69
  * Cache configuration
@@ -78,11 +80,10 @@ export interface ICacheConfig {
78
80
  }
79
81
  /**
80
82
  * Analyzer configuration
83
+ * Note: Smart analysis is always enabled; this config only controls advanced options
81
84
  */
82
85
  export interface IAnalyzerConfig {
83
- /** Whether analyzer is enabled */
84
- enabled?: boolean;
85
- /** Whether to use AI refinement for selection */
86
+ /** Whether to use AI refinement for selection (advanced, disabled by default) */
86
87
  useAIRefinement?: boolean;
87
88
  /** AI model to use for refinement */
88
89
  aiModel?: string;
@@ -230,3 +231,70 @@ export interface IAnalysisResult {
230
231
  /** Analysis duration in ms */
231
232
  analysisDuration: number;
232
233
  }
234
+ /**
235
+ * Configuration for iterative context building
236
+ */
237
+ export interface IIterativeConfig {
238
+ /** Maximum number of iterations allowed */
239
+ maxIterations?: number;
240
+ /** Maximum files to request in first iteration */
241
+ firstPassFileLimit?: number;
242
+ /** Maximum files to request in subsequent iterations */
243
+ subsequentPassFileLimit?: number;
244
+ /** Temperature for AI decision making (0-1) */
245
+ temperature?: number;
246
+ /** Model to use for iterative decisions */
247
+ model?: string;
248
+ }
249
+ /**
250
+ * AI decision for file selection
251
+ */
252
+ export interface IFileSelectionDecision {
253
+ /** AI's reasoning for file selection */
254
+ reasoning: string;
255
+ /** File paths to load */
256
+ filesToLoad: string[];
257
+ /** Estimated tokens needed */
258
+ estimatedTokensNeeded?: number;
259
+ }
260
+ /**
261
+ * AI decision for context sufficiency
262
+ */
263
+ export interface IContextSufficiencyDecision {
264
+ /** Whether context is sufficient */
265
+ sufficient: boolean;
266
+ /** AI's reasoning */
267
+ reasoning: string;
268
+ /** Additional files needed (if not sufficient) */
269
+ additionalFilesNeeded?: string[];
270
+ }
271
+ /**
272
+ * State for a single iteration
273
+ */
274
+ export interface IIterationState {
275
+ /** Iteration number (1-based) */
276
+ iteration: number;
277
+ /** Files loaded in this iteration */
278
+ filesLoaded: IFileInfo[];
279
+ /** Tokens used in this iteration */
280
+ tokensUsed: number;
281
+ /** Total tokens used so far */
282
+ totalTokensUsed: number;
283
+ /** AI decision made in this iteration */
284
+ decision: IFileSelectionDecision | IContextSufficiencyDecision;
285
+ /** Duration of this iteration in ms */
286
+ duration: number;
287
+ }
288
+ /**
289
+ * Result of iterative context building
290
+ */
291
+ export interface IIterativeContextResult extends IContextResult {
292
+ /** Number of iterations performed */
293
+ iterationCount: number;
294
+ /** Details of each iteration */
295
+ iterations: IIterationState[];
296
+ /** Total API calls made */
297
+ apiCallCount: number;
298
+ /** Total duration in ms */
299
+ totalDuration: number;
300
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@git.zone/tsdoc",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "private": false,
5
5
  "description": "A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.",
6
6
  "type": "module",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tsdoc',
6
- version: '1.6.0',
6
+ version: '1.7.0',
7
7
  description: 'A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.'
8
8
  }
package/ts/cli.ts CHANGED
@@ -31,18 +31,18 @@ export const run = async () => {
31
31
  tsdocCli.addCommand('aidoc').subscribe(async (argvArg) => {
32
32
  const aidocInstance = new AiDoc();
33
33
  await aidocInstance.start();
34
-
34
+
35
35
  // Get context token count if requested
36
36
  if (argvArg.tokens || argvArg.showTokens) {
37
37
  logger.log('info', `Calculating context token count...`);
38
38
  const tokenCount = await aidocInstance.getProjectContextTokenCount(paths.cwd);
39
39
  logger.log('ok', `Total context token count: ${tokenCount}`);
40
-
40
+
41
41
  if (argvArg.tokensOnly) {
42
42
  return; // Exit early if we only want token count
43
43
  }
44
44
  }
45
-
45
+
46
46
  logger.log('info', `Generating new readme...`);
47
47
  logger.log('info', `This may take some time...`);
48
48
  await aidocInstance.buildReadme(paths.cwd);
@@ -54,67 +54,50 @@ export const run = async () => {
54
54
  tsdocCli.addCommand('tokens').subscribe(async (argvArg) => {
55
55
  const aidocInstance = new AiDoc();
56
56
  await aidocInstance.start();
57
-
57
+
58
58
  logger.log('info', `Calculating context token count...`);
59
-
60
- // Determine context mode based on args
61
- let contextMode: context.ContextMode = 'full';
62
- if (argvArg.trim || argvArg.trimmed) {
63
- contextMode = 'trimmed';
64
- } else if (argvArg.summarize || argvArg.summarized) {
65
- contextMode = 'summarized';
66
- }
67
-
59
+
68
60
  // Get task type if specified
69
61
  let taskType: context.TaskType | undefined = undefined;
70
62
  if (argvArg.task) {
71
63
  if (['readme', 'commit', 'description'].includes(argvArg.task)) {
72
64
  taskType = argvArg.task as context.TaskType;
73
65
  } else {
74
- logger.log('warn', `Unknown task type: ${argvArg.task}. Using default context.`);
66
+ logger.log('warn', `Unknown task type: ${argvArg.task}. Using default (readme).`);
67
+ taskType = 'readme';
75
68
  }
69
+ } else {
70
+ // Default to readme if no task specified
71
+ taskType = 'readme';
76
72
  }
77
-
78
- // Use enhanced context
73
+
74
+ // Use iterative context building
79
75
  const taskFactory = new context.TaskContextFactory(paths.cwd);
80
76
  await taskFactory.initialize();
81
-
82
- let contextResult: context.IContextResult;
83
-
77
+
78
+ let contextResult: context.IIterativeContextResult;
79
+
84
80
  if (argvArg.all) {
85
81
  // Show stats for all task types
86
82
  const stats = await taskFactory.getTokenStats();
87
-
83
+
88
84
  logger.log('ok', 'Token statistics by task:');
89
85
  for (const [task, data] of Object.entries(stats)) {
90
86
  logger.log('info', `\n${task.toUpperCase()}:`);
91
87
  logger.log('info', ` Tokens: ${data.tokenCount}`);
92
88
  logger.log('info', ` Token savings: ${data.savings}`);
93
89
  logger.log('info', ` Files: ${data.includedFiles} included, ${data.trimmedFiles} trimmed, ${data.excludedFiles} excluded`);
94
-
90
+
95
91
  // Calculate percentage of model context
96
92
  const o4MiniPercentage = (data.tokenCount / 200000 * 100).toFixed(2);
97
93
  logger.log('info', ` Context usage: ${o4MiniPercentage}% of o4-mini (200K tokens)`);
98
94
  }
99
-
95
+
100
96
  return;
101
97
  }
102
-
103
- if (taskType) {
104
- // Get context for specific task
105
- contextResult = await taskFactory.createContextForTask(taskType);
106
- } else {
107
- // Get generic context with specified mode
108
- const enhancedContext = new context.EnhancedContext(paths.cwd);
109
- await enhancedContext.initialize();
110
- enhancedContext.setContextMode(contextMode);
111
-
112
- if (argvArg.maxTokens) {
113
- enhancedContext.setTokenBudget(parseInt(argvArg.maxTokens, 10));
114
- }
115
-
116
- contextResult = await enhancedContext.buildContext();
117
- }
98
+
99
+ // Get context for specific task
100
+ contextResult = await taskFactory.createContextForTask(taskType);
118
101
 
119
102
  // Display results
120
103
  logger.log('ok', `Total context token count: ${contextResult.tokenCount}`);
@@ -9,7 +9,8 @@ import type {
9
9
  ICacheConfig,
10
10
  IAnalyzerConfig,
11
11
  IPrioritizationWeights,
12
- ITierConfig
12
+ ITierConfig,
13
+ IIterativeConfig
13
14
  } from './types.js';
14
15
 
15
16
  /**
@@ -85,7 +86,6 @@ export class ConfigManager {
85
86
  directory: undefined // Will be set to .nogit/context-cache by ContextCache
86
87
  },
87
88
  analyzer: {
88
- enabled: true,
89
89
  useAIRefinement: false, // Disabled by default for now
90
90
  aiModel: 'haiku'
91
91
  },
@@ -99,6 +99,13 @@ export class ConfigManager {
99
99
  essential: { minScore: 0.8, trimLevel: 'none' },
100
100
  important: { minScore: 0.5, trimLevel: 'light' },
101
101
  optional: { minScore: 0.2, trimLevel: 'aggressive' }
102
+ },
103
+ iterative: {
104
+ maxIterations: 5,
105
+ firstPassFileLimit: 10,
106
+ subsequentPassFileLimit: 5,
107
+ temperature: 0.3,
108
+ model: 'gpt-4-turbo-preview'
102
109
  }
103
110
  };
104
111
  }
@@ -157,15 +164,15 @@ export class ConfigManager {
157
164
  */
158
165
  private mergeConfigs(defaultConfig: IContextConfig, userConfig: Partial<IContextConfig>): IContextConfig {
159
166
  const result: IContextConfig = { ...defaultConfig };
160
-
167
+
161
168
  // Merge top-level properties
162
169
  if (userConfig.maxTokens !== undefined) result.maxTokens = userConfig.maxTokens;
163
170
  if (userConfig.defaultMode !== undefined) result.defaultMode = userConfig.defaultMode;
164
-
171
+
165
172
  // Merge task-specific settings
166
173
  if (userConfig.taskSpecificSettings) {
167
174
  result.taskSpecificSettings = result.taskSpecificSettings || {};
168
-
175
+
169
176
  // For each task type, merge settings
170
177
  (['readme', 'commit', 'description'] as TaskType[]).forEach(taskType => {
171
178
  if (userConfig.taskSpecificSettings?.[taskType]) {
@@ -176,7 +183,7 @@ export class ConfigManager {
176
183
  }
177
184
  });
178
185
  }
179
-
186
+
180
187
  // Merge trimming configuration
181
188
  if (userConfig.trimming) {
182
189
  result.trimming = {
@@ -217,6 +224,14 @@ export class ConfigManager {
217
224
  };
218
225
  }
219
226
 
227
+ // Merge iterative configuration
228
+ if (userConfig.iterative) {
229
+ result.iterative = {
230
+ ...result.iterative,
231
+ ...userConfig.iterative
232
+ };
233
+ }
234
+
220
235
  return result;
221
236
  }
222
237
 
@@ -306,7 +321,7 @@ export class ConfigManager {
306
321
  * Get analyzer configuration
307
322
  */
308
323
  public getAnalyzerConfig(): IAnalyzerConfig {
309
- return this.config.analyzer || { enabled: true, useAIRefinement: false, aiModel: 'haiku' };
324
+ return this.config.analyzer || { useAIRefinement: false, aiModel: 'haiku' };
310
325
  }
311
326
 
312
327
  /**
@@ -332,6 +347,19 @@ export class ConfigManager {
332
347
  };
333
348
  }
334
349
 
350
+ /**
351
+ * Get iterative configuration
352
+ */
353
+ public getIterativeConfig(): IIterativeConfig {
354
+ return this.config.iterative || {
355
+ maxIterations: 5,
356
+ firstPassFileLimit: 10,
357
+ subsequentPassFileLimit: 5,
358
+ temperature: 0.3,
359
+ model: 'gpt-4-turbo-preview'
360
+ };
361
+ }
362
+
335
363
  /**
336
364
  * Clear the config cache (force reload on next access)
337
365
  */
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../plugins.js';
2
2
  import * as fs from 'fs';
3
3
  import type { ICacheEntry, ICacheConfig } from './types.js';
4
+ import { logger } from '../logging.js';
4
5
 
5
6
  /**
6
7
  * ContextCache provides persistent caching of file contents and token counts
@@ -69,181 +69,7 @@ export class EnhancedContext {
69
69
  public setTokenBudget(maxTokens: number): void {
70
70
  this.tokenBudget = maxTokens;
71
71
  }
72
-
73
- /**
74
- * Gather files from the project
75
- * @param includePaths Optional paths to include
76
- * @param excludePaths Optional paths to exclude
77
- */
78
- public async gatherFiles(includePaths?: string[], excludePaths?: string[]): Promise<Record<string, plugins.smartfile.SmartFile | plugins.smartfile.SmartFile[]>> {
79
- const smartfilePackageJSON = await plugins.smartfile.SmartFile.fromFilePath(
80
- plugins.path.join(this.projectDir, 'package.json'),
81
- this.projectDir,
82
- );
83
-
84
- const smartfilesReadme = await plugins.smartfile.SmartFile.fromFilePath(
85
- plugins.path.join(this.projectDir, 'readme.md'),
86
- this.projectDir,
87
- );
88
72
 
89
- const smartfilesReadmeHints = await plugins.smartfile.SmartFile.fromFilePath(
90
- plugins.path.join(this.projectDir, 'readme.hints.md'),
91
- this.projectDir,
92
- );
93
-
94
- const smartfilesNpmextraJSON = await plugins.smartfile.SmartFile.fromFilePath(
95
- plugins.path.join(this.projectDir, 'npmextra.json'),
96
- this.projectDir,
97
- );
98
-
99
- // Use provided include paths or default to all TypeScript files
100
- const includeGlobs = includePaths?.map(path => `${path}/**/*.ts`) || ['ts*/**/*.ts'];
101
-
102
- // Get TypeScript files
103
- const smartfilesModPromises = includeGlobs.map(glob =>
104
- plugins.smartfile.fs.fileTreeToObject(this.projectDir, glob)
105
- );
106
-
107
- const smartfilesModArrays = await Promise.all(smartfilesModPromises);
108
-
109
- // Flatten the arrays
110
- const smartfilesMod: plugins.smartfile.SmartFile[] = [];
111
- smartfilesModArrays.forEach(array => {
112
- smartfilesMod.push(...array);
113
- });
114
-
115
- // Get test files if not excluded
116
- let smartfilesTest: plugins.smartfile.SmartFile[] = [];
117
- if (!excludePaths?.includes('test/')) {
118
- smartfilesTest = await plugins.smartfile.fs.fileTreeToObject(
119
- this.projectDir,
120
- 'test/**/*.ts',
121
- );
122
- }
123
-
124
- return {
125
- smartfilePackageJSON,
126
- smartfilesReadme,
127
- smartfilesReadmeHints,
128
- smartfilesNpmextraJSON,
129
- smartfilesMod,
130
- smartfilesTest,
131
- };
132
- }
133
-
134
- /**
135
- * Convert files to context string
136
- * @param files The files to convert
137
- * @param mode The context mode to use
138
- */
139
- public async convertFilesToContext(
140
- files: plugins.smartfile.SmartFile[],
141
- mode: ContextMode = this.contextMode
142
- ): Promise<string> {
143
- // Reset context result
144
- this.contextResult = {
145
- context: '',
146
- tokenCount: 0,
147
- includedFiles: [],
148
- trimmedFiles: [],
149
- excludedFiles: [],
150
- tokenSavings: 0
151
- };
152
-
153
- let totalTokenCount = 0;
154
- let totalOriginalTokens = 0;
155
-
156
- // Convert SmartFile objects to IFileMetadata for analysis
157
- const metadata: IFileMetadata[] = files.map(sf => ({
158
- path: sf.path,
159
- relativePath: sf.relative,
160
- size: sf.contents.toString().length,
161
- mtime: Date.now(), // SmartFile doesn't expose mtime, use current time
162
- estimatedTokens: this.countTokens(sf.contents.toString()),
163
- importanceScore: 0
164
- }));
165
-
166
- // Analyze files using ContextAnalyzer to get smart prioritization
167
- // (Note: This requires task type which we'll pass from buildContext)
168
- // For now, sort files by estimated tokens (smaller files first for better efficiency)
169
- const sortedFiles = [...files].sort((a, b) => {
170
- const aTokens = this.countTokens(a.contents.toString());
171
- const bTokens = this.countTokens(b.contents.toString());
172
- return aTokens - bTokens;
173
- });
174
-
175
- const processedFiles: string[] = [];
176
-
177
- for (const smartfile of sortedFiles) {
178
- // Calculate original token count
179
- const originalContent = smartfile.contents.toString();
180
- const originalTokenCount = this.countTokens(originalContent);
181
- totalOriginalTokens += originalTokenCount;
182
-
183
- // Apply trimming based on mode
184
- let processedContent = originalContent;
185
-
186
- if (mode !== 'full') {
187
- processedContent = this.trimmer.trimFile(
188
- smartfile.relative,
189
- originalContent,
190
- mode
191
- );
192
- }
193
-
194
- // Calculate new token count
195
- const processedTokenCount = this.countTokens(processedContent);
196
-
197
- // Check if we have budget for this file
198
- if (totalTokenCount + processedTokenCount > this.tokenBudget) {
199
- // We don't have budget for this file
200
- this.contextResult.excludedFiles.push({
201
- path: smartfile.path,
202
- contents: originalContent,
203
- relativePath: smartfile.relative,
204
- tokenCount: originalTokenCount
205
- });
206
- continue;
207
- }
208
-
209
- // Format the file for context
210
- const formattedContent = `
211
- ====== START OF FILE ${smartfile.relative} ======
212
-
213
- ${processedContent}
214
-
215
- ====== END OF FILE ${smartfile.relative} ======
216
- `;
217
-
218
- processedFiles.push(formattedContent);
219
- totalTokenCount += processedTokenCount;
220
-
221
- // Track file in appropriate list
222
- const fileInfo: IFileInfo = {
223
- path: smartfile.path,
224
- contents: processedContent,
225
- relativePath: smartfile.relative,
226
- tokenCount: processedTokenCount
227
- };
228
-
229
- if (mode === 'full' || processedContent === originalContent) {
230
- this.contextResult.includedFiles.push(fileInfo);
231
- } else {
232
- this.contextResult.trimmedFiles.push(fileInfo);
233
- this.contextResult.tokenSavings += (originalTokenCount - processedTokenCount);
234
- }
235
- }
236
-
237
- // Join all processed files
238
- const context = processedFiles.join('\n');
239
-
240
- // Update context result
241
- this.contextResult.context = context;
242
- this.contextResult.tokenCount = totalTokenCount;
243
-
244
- return context;
245
- }
246
-
247
73
  /**
248
74
  * Convert files to context with smart analysis and prioritization
249
75
  * @param metadata - File metadata to analyze
@@ -393,88 +219,45 @@ ${processedContent}
393
219
  }
394
220
 
395
221
  /**
396
- * Build context for the project
397
- * @param taskType Optional task type for task-specific context
222
+ * Build context for the project using smart analysis
223
+ * @param taskType Task type for context-aware prioritization (defaults to 'description')
398
224
  */
399
225
  public async buildContext(taskType?: TaskType): Promise<IContextResult> {
400
226
  // Initialize if needed
401
227
  if (this.tokenBudget === 0) {
402
228
  await this.initialize();
403
229
  }
404
-
405
- // Get task-specific configuration if a task type is provided
406
- if (taskType) {
407
- const taskConfig = this.configManager.getTaskConfig(taskType);
408
- if (taskConfig.mode) {
409
- this.setContextMode(taskConfig.mode);
410
- }
411
- }
412
-
413
- // Check if analyzer is enabled in config
414
- const analyzerConfig = this.configManager.getAnalyzerConfig();
415
- const useAnalyzer = analyzerConfig.enabled && taskType;
416
-
417
- if (useAnalyzer) {
418
- // Use new smart context building with lazy loading and analysis
419
- const taskConfig = this.configManager.getTaskConfig(taskType!);
420
-
421
- // Build globs for scanning
422
- const includeGlobs = taskConfig?.includePaths?.map(p => `${p}/**/*.ts`) || [
423
- 'ts/**/*.ts',
424
- 'ts*/**/*.ts'
425
- ];
426
-
427
- // Add config files
428
- const configGlobs = [
429
- 'package.json',
430
- 'readme.md',
431
- 'readme.hints.md',
432
- 'npmextra.json'
433
- ];
434
-
435
- // Scan files for metadata (fast, doesn't load contents)
436
- const metadata = await this.lazyLoader.scanFiles([...configGlobs, ...includeGlobs]);
437
-
438
- // Use analyzer to build context with smart prioritization
439
- await this.convertFilesToContextWithAnalysis(metadata, taskType!, this.contextMode);
440
- } else {
441
- // Fall back to old method for backward compatibility
442
- const taskConfig = taskType ? this.configManager.getTaskConfig(taskType) : undefined;
443
- const files = await this.gatherFiles(
444
- taskConfig?.includePaths,
445
- taskConfig?.excludePaths
446
- );
447
-
448
- // Convert files to context
449
- // Create an array of all files to process
450
- const allFiles: plugins.smartfile.SmartFile[] = [];
451
-
452
- // Add individual files
453
- if (files.smartfilePackageJSON) allFiles.push(files.smartfilePackageJSON as plugins.smartfile.SmartFile);
454
- if (files.smartfilesReadme) allFiles.push(files.smartfilesReadme as plugins.smartfile.SmartFile);
455
- if (files.smartfilesReadmeHints) allFiles.push(files.smartfilesReadmeHints as plugins.smartfile.SmartFile);
456
- if (files.smartfilesNpmextraJSON) allFiles.push(files.smartfilesNpmextraJSON as plugins.smartfile.SmartFile);
457
-
458
- // Add arrays of files
459
- if (files.smartfilesMod) {
460
- if (Array.isArray(files.smartfilesMod)) {
461
- allFiles.push(...files.smartfilesMod);
462
- } else {
463
- allFiles.push(files.smartfilesMod);
464
- }
465
- }
466
230
 
467
- if (files.smartfilesTest) {
468
- if (Array.isArray(files.smartfilesTest)) {
469
- allFiles.push(...files.smartfilesTest);
470
- } else {
471
- allFiles.push(files.smartfilesTest);
472
- }
473
- }
231
+ // Smart context building always requires a task type for optimal prioritization
232
+ // Default to 'description' if not provided
233
+ const effectiveTaskType = taskType || 'description';
474
234
 
475
- await this.convertFilesToContext(allFiles);
235
+ // Get task-specific configuration
236
+ const taskConfig = this.configManager.getTaskConfig(effectiveTaskType);
237
+ if (taskConfig.mode) {
238
+ this.setContextMode(taskConfig.mode);
476
239
  }
477
240
 
241
+ // Build globs for scanning
242
+ const includeGlobs = taskConfig?.includePaths?.map(p => `${p}/**/*.ts`) || [
243
+ 'ts/**/*.ts',
244
+ 'ts*/**/*.ts'
245
+ ];
246
+
247
+ // Add config files
248
+ const configGlobs = [
249
+ 'package.json',
250
+ 'readme.md',
251
+ 'readme.hints.md',
252
+ 'npmextra.json'
253
+ ];
254
+
255
+ // Scan files for metadata (fast, doesn't load contents)
256
+ const metadata = await this.lazyLoader.scanFiles([...configGlobs, ...includeGlobs]);
257
+
258
+ // Use smart analyzer to build context with intelligent prioritization
259
+ await this.convertFilesToContextWithAnalysis(metadata, effectiveTaskType, this.contextMode);
260
+
478
261
  return this.contextResult;
479
262
  }
480
263
 
@@ -22,7 +22,9 @@ import type {
22
22
  ICacheEntry,
23
23
  IFileDependencies,
24
24
  IFileAnalysis,
25
- IAnalysisResult
25
+ IAnalysisResult,
26
+ IIterativeConfig,
27
+ IIterativeContextResult
26
28
  } from './types.js';
27
29
 
28
30
  export {
@@ -54,5 +56,7 @@ export type {
54
56
  ICacheEntry,
55
57
  IFileDependencies,
56
58
  IFileAnalysis,
57
- IAnalysisResult
59
+ IAnalysisResult,
60
+ IIterativeConfig,
61
+ IIterativeContextResult
58
62
  };