Compare commits
	
		
			4 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0a3080518f | |||
| d0a4ddbb4b | |||
| 481339d3cb | |||
| ebc3d760af | 
@@ -1,5 +1,13 @@
 | 
				
			|||||||
# Changelog
 | 
					# Changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2025-11-03 - 1.8.0 - feat(context)
 | 
				
			||||||
 | 
					Wire OpenAI provider through task context factory and add git-diff support to iterative context builder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Pass AiDoc.openaiInstance through TaskContextFactory into IterativeContextBuilder to reuse the same OpenAI provider and avoid reinitialization.
 | 
				
			||||||
 | 
					- IterativeContextBuilder now accepts an optional OpenAiProvider and an additionalContext string; when provided, git diffs (or other extra context) are prepended to the AI context and token counts are updated.
 | 
				
			||||||
 | 
					- createContextForCommit now forwards the git diff into the iterative builder so commit-specific context includes the diff.
 | 
				
			||||||
 | 
					- Updated aidocs_classes (commit, description, readme) to supply the existing openaiInstance when creating the TaskContextFactory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 2025-11-03 - 1.7.0 - feat(IterativeContextBuilder)
 | 
					## 2025-11-03 - 1.7.0 - feat(IterativeContextBuilder)
 | 
				
			||||||
Add iterative AI-driven context builder and integrate into task factory; add tests and iterative configuration
 | 
					Add iterative AI-driven context builder and integrate into task factory; add tests and iterative configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "@git.zone/tsdoc",
 | 
					  "name": "@git.zone/tsdoc",
 | 
				
			||||||
  "version": "1.7.0",
 | 
					  "version": "1.8.1",
 | 
				
			||||||
  "private": false,
 | 
					  "private": false,
 | 
				
			||||||
  "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.",
 | 
					  "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.",
 | 
				
			||||||
  "type": "module",
 | 
					  "type": "module",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,10 @@ tap.test('should build commit object', async () => {
 | 
				
			|||||||
  expect(commitObject).toHaveProperty('recommendedNextVersionLevel');
 | 
					  expect(commitObject).toHaveProperty('recommendedNextVersionLevel');
 | 
				
			||||||
  expect(commitObject).toHaveProperty('recommendedNextVersionScope');
 | 
					  expect(commitObject).toHaveProperty('recommendedNextVersionScope');
 | 
				
			||||||
  expect(commitObject).toHaveProperty('recommendedNextVersionMessage');
 | 
					  expect(commitObject).toHaveProperty('recommendedNextVersionMessage');
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
})
 | 
					tap.test('should stop AIdocs', async () => {
 | 
				
			||||||
 | 
					  await aidocs.stop();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tap.start();
 | 
					tap.start();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +0,0 @@
 | 
				
			|||||||
import { expect, tap } from '@push.rocks/tapbundle';
 | 
					 | 
				
			||||||
import * as tsdoc from '../ts/index.js';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tap.test('first test', async () => {
 | 
					 | 
				
			||||||
  console.log('test');
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tap.start();
 | 
					 | 
				
			||||||
@@ -3,6 +3,6 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export const commitinfo = {
 | 
					export const commitinfo = {
 | 
				
			||||||
  name: '@git.zone/tsdoc',
 | 
					  name: '@git.zone/tsdoc',
 | 
				
			||||||
  version: '1.7.0',
 | 
					  version: '1.8.0',
 | 
				
			||||||
  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.'
 | 
					  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.'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,9 +30,20 @@ export class Commit {
 | 
				
			|||||||
    const diffStringArray = await gitRepo.getUncommittedDiff([
 | 
					    const diffStringArray = await gitRepo.getUncommittedDiff([
 | 
				
			||||||
      'pnpm-lock.yaml',
 | 
					      'pnpm-lock.yaml',
 | 
				
			||||||
      'package-lock.json',
 | 
					      'package-lock.json',
 | 
				
			||||||
 | 
					      'npm-shrinkwrap.json',
 | 
				
			||||||
 | 
					      'yarn.lock',
 | 
				
			||||||
 | 
					      'deno.lock',
 | 
				
			||||||
 | 
					      'bun.lockb',
 | 
				
			||||||
 | 
					      '.claude/*',
 | 
				
			||||||
 | 
					      '.cursor/*',
 | 
				
			||||||
 | 
					      '.vscode/*',
 | 
				
			||||||
 | 
					      '.idea/*',
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
    // Use the new TaskContextFactory for optimized context
 | 
					    // Use the new TaskContextFactory for optimized context
 | 
				
			||||||
    const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(this.projectDir);
 | 
					    const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(
 | 
				
			||||||
 | 
					      this.projectDir,
 | 
				
			||||||
 | 
					      this.aiDocsRef.openaiInstance
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
    await taskContextFactory.initialize();
 | 
					    await taskContextFactory.initialize();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Generate context specifically for commit task
 | 
					    // Generate context specifically for commit task
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,10 @@ export class Description {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  public async build() {
 | 
					  public async build() {
 | 
				
			||||||
    // Use the new TaskContextFactory for optimized context
 | 
					    // Use the new TaskContextFactory for optimized context
 | 
				
			||||||
    const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(this.projectDir);
 | 
					    const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(
 | 
				
			||||||
 | 
					      this.projectDir,
 | 
				
			||||||
 | 
					      this.aiDocsRef.openaiInstance
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
    await taskContextFactory.initialize();
 | 
					    await taskContextFactory.initialize();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Generate context specifically for description task
 | 
					    // Generate context specifically for description task
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,10 @@ export class Readme {
 | 
				
			|||||||
    let finalReadmeString = ``;
 | 
					    let finalReadmeString = ``;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Use the new TaskContextFactory for optimized context
 | 
					    // Use the new TaskContextFactory for optimized context
 | 
				
			||||||
    const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(this.projectDir);
 | 
					    const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(
 | 
				
			||||||
 | 
					      this.projectDir,
 | 
				
			||||||
 | 
					      this.aiDocsRef.openaiInstance
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
    await taskContextFactory.initialize();
 | 
					    await taskContextFactory.initialize();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Generate context specifically for readme task
 | 
					    // Generate context specifically for readme task
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,7 +64,7 @@ export class AiDoc {
 | 
				
			|||||||
        await this.npmextraKV.writeKey('OPENAI_TOKEN', this.openaiToken);
 | 
					        await this.npmextraKV.writeKey('OPENAI_TOKEN', this.openaiToken);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!this.openaiToken) {
 | 
					    if (!this.openaiToken && this.npmextraKV) {
 | 
				
			||||||
      this.openaiToken = await this.npmextraKV.readKey('OPENAI_TOKEN');
 | 
					      this.openaiToken = await this.npmextraKV.readKey('OPENAI_TOKEN');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,7 +76,11 @@ export class AiDoc {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async stop() {
 | 
					  public async stop() {
 | 
				
			||||||
    await this.openaiInstance.stop();
 | 
					    if (this.openaiInstance) {
 | 
				
			||||||
 | 
					      await this.openaiInstance.stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // No explicit cleanup needed for npmextraKV or aidocInteract
 | 
				
			||||||
 | 
					    // They don't keep event loop alive
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async buildReadme(projectDirArg: string) {
 | 
					  public async buildReadme(projectDirArg: string) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,17 +28,24 @@ export class IterativeContextBuilder {
 | 
				
			|||||||
  private config: Required<IIterativeConfig>;
 | 
					  private config: Required<IIterativeConfig>;
 | 
				
			||||||
  private tokenBudget: number = 190000;
 | 
					  private tokenBudget: number = 190000;
 | 
				
			||||||
  private openaiInstance: plugins.smartai.OpenAiProvider;
 | 
					  private openaiInstance: plugins.smartai.OpenAiProvider;
 | 
				
			||||||
 | 
					  private externalOpenaiInstance?: plugins.smartai.OpenAiProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Creates a new IterativeContextBuilder
 | 
					   * Creates a new IterativeContextBuilder
 | 
				
			||||||
   * @param projectRoot - Root directory of the project
 | 
					   * @param projectRoot - Root directory of the project
 | 
				
			||||||
   * @param config - Iterative configuration
 | 
					   * @param config - Iterative configuration
 | 
				
			||||||
 | 
					   * @param openaiInstance - Optional pre-configured OpenAI provider instance
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  constructor(projectRoot: string, config?: Partial<IIterativeConfig>) {
 | 
					  constructor(
 | 
				
			||||||
 | 
					    projectRoot: string,
 | 
				
			||||||
 | 
					    config?: Partial<IIterativeConfig>,
 | 
				
			||||||
 | 
					    openaiInstance?: plugins.smartai.OpenAiProvider
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
    this.projectRoot = projectRoot;
 | 
					    this.projectRoot = projectRoot;
 | 
				
			||||||
    this.lazyLoader = new LazyFileLoader(projectRoot);
 | 
					    this.lazyLoader = new LazyFileLoader(projectRoot);
 | 
				
			||||||
    this.cache = new ContextCache(projectRoot);
 | 
					    this.cache = new ContextCache(projectRoot);
 | 
				
			||||||
    this.analyzer = new ContextAnalyzer(projectRoot);
 | 
					    this.analyzer = new ContextAnalyzer(projectRoot);
 | 
				
			||||||
 | 
					    this.externalOpenaiInstance = openaiInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Default configuration
 | 
					    // Default configuration
 | 
				
			||||||
    this.config = {
 | 
					    this.config = {
 | 
				
			||||||
@@ -60,24 +67,30 @@ export class IterativeContextBuilder {
 | 
				
			|||||||
    await configManager.initialize(this.projectRoot);
 | 
					    await configManager.initialize(this.projectRoot);
 | 
				
			||||||
    this.tokenBudget = configManager.getMaxTokens();
 | 
					    this.tokenBudget = configManager.getMaxTokens();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Initialize OpenAI instance
 | 
					    // Use external OpenAI instance if provided, otherwise create a new one
 | 
				
			||||||
    const qenvInstance = new plugins.qenv.Qenv();
 | 
					    if (this.externalOpenaiInstance) {
 | 
				
			||||||
    const openaiToken = await qenvInstance.getEnvVarOnDemand('OPENAI_TOKEN');
 | 
					      this.openaiInstance = this.externalOpenaiInstance;
 | 
				
			||||||
    if (!openaiToken) {
 | 
					    } else {
 | 
				
			||||||
      throw new Error('OPENAI_TOKEN environment variable is required for iterative context building');
 | 
					      // Initialize OpenAI instance from environment
 | 
				
			||||||
 | 
					      const qenvInstance = new plugins.qenv.Qenv();
 | 
				
			||||||
 | 
					      const openaiToken = await qenvInstance.getEnvVarOnDemand('OPENAI_TOKEN');
 | 
				
			||||||
 | 
					      if (!openaiToken) {
 | 
				
			||||||
 | 
					        throw new Error('OPENAI_TOKEN environment variable is required for iterative context building');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.openaiInstance = new plugins.smartai.OpenAiProvider({
 | 
				
			||||||
 | 
					        openaiToken,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      await this.openaiInstance.start();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.openaiInstance = new plugins.smartai.OpenAiProvider({
 | 
					 | 
				
			||||||
      openaiToken,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    await this.openaiInstance.start();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Build context iteratively using AI decision making
 | 
					   * Build context iteratively using AI decision making
 | 
				
			||||||
   * @param taskType - Type of task being performed
 | 
					   * @param taskType - Type of task being performed
 | 
				
			||||||
 | 
					   * @param additionalContext - Optional additional context (e.g., git diff for commit tasks)
 | 
				
			||||||
   * @returns Complete iterative context result
 | 
					   * @returns Complete iterative context result
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  public async buildContextIteratively(taskType: TaskType): Promise<IIterativeContextResult> {
 | 
					  public async buildContextIteratively(taskType: TaskType, additionalContext?: string): Promise<IIterativeContextResult> {
 | 
				
			||||||
    const startTime = Date.now();
 | 
					    const startTime = Date.now();
 | 
				
			||||||
    logger.log('info', '🤖 Starting iterative context building...');
 | 
					    logger.log('info', '🤖 Starting iterative context building...');
 | 
				
			||||||
    logger.log('info', `   Task: ${taskType}, Budget: ${this.tokenBudget} tokens, Max iterations: ${this.config.maxIterations}`);
 | 
					    logger.log('info', `   Task: ${taskType}, Budget: ${this.tokenBudget} tokens, Max iterations: ${this.config.maxIterations}`);
 | 
				
			||||||
@@ -100,6 +113,21 @@ export class IterativeContextBuilder {
 | 
				
			|||||||
    let loadedContent = '';
 | 
					    let loadedContent = '';
 | 
				
			||||||
    const includedFiles: IFileInfo[] = [];
 | 
					    const includedFiles: IFileInfo[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If additional context (e.g., git diff) is provided, prepend it
 | 
				
			||||||
 | 
					    if (additionalContext) {
 | 
				
			||||||
 | 
					      const diffSection = `
 | 
				
			||||||
 | 
					====== GIT DIFF ======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${additionalContext}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					====== END OF GIT DIFF ======
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					      loadedContent = diffSection;
 | 
				
			||||||
 | 
					      const diffTokens = this.countTokens(diffSection);
 | 
				
			||||||
 | 
					      totalTokensUsed += diffTokens;
 | 
				
			||||||
 | 
					      logger.log('info', `📝 Added git diff to context (${diffTokens} tokens)`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Phase 3: Iterative file selection and loading
 | 
					    // Phase 3: Iterative file selection and loading
 | 
				
			||||||
    for (let iteration = 1; iteration <= this.config.maxIterations; iteration++) {
 | 
					    for (let iteration = 1; iteration <= this.config.maxIterations; iteration++) {
 | 
				
			||||||
      const iterationStart = Date.now();
 | 
					      const iterationStart = Date.now();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,14 +9,17 @@ import type { IIterativeContextResult, TaskType } from './types.js';
 | 
				
			|||||||
export class TaskContextFactory {
 | 
					export class TaskContextFactory {
 | 
				
			||||||
  private projectDir: string;
 | 
					  private projectDir: string;
 | 
				
			||||||
  private configManager: ConfigManager;
 | 
					  private configManager: ConfigManager;
 | 
				
			||||||
 | 
					  private openaiInstance?: any; // OpenAI provider instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Create a new TaskContextFactory
 | 
					   * Create a new TaskContextFactory
 | 
				
			||||||
   * @param projectDirArg The project directory
 | 
					   * @param projectDirArg The project directory
 | 
				
			||||||
 | 
					   * @param openaiInstance Optional pre-configured OpenAI provider instance
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  constructor(projectDirArg: string) {
 | 
					  constructor(projectDirArg: string, openaiInstance?: any) {
 | 
				
			||||||
    this.projectDir = projectDirArg;
 | 
					    this.projectDir = projectDirArg;
 | 
				
			||||||
    this.configManager = ConfigManager.getInstance();
 | 
					    this.configManager = ConfigManager.getInstance();
 | 
				
			||||||
 | 
					    this.openaiInstance = openaiInstance;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@@ -32,7 +35,8 @@ export class TaskContextFactory {
 | 
				
			|||||||
  public async createContextForReadme(): Promise<IIterativeContextResult> {
 | 
					  public async createContextForReadme(): Promise<IIterativeContextResult> {
 | 
				
			||||||
    const iterativeBuilder = new IterativeContextBuilder(
 | 
					    const iterativeBuilder = new IterativeContextBuilder(
 | 
				
			||||||
      this.projectDir,
 | 
					      this.projectDir,
 | 
				
			||||||
      this.configManager.getIterativeConfig()
 | 
					      this.configManager.getIterativeConfig(),
 | 
				
			||||||
 | 
					      this.openaiInstance
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    await iterativeBuilder.initialize();
 | 
					    await iterativeBuilder.initialize();
 | 
				
			||||||
    return await iterativeBuilder.buildContextIteratively('readme');
 | 
					    return await iterativeBuilder.buildContextIteratively('readme');
 | 
				
			||||||
@@ -44,7 +48,8 @@ export class TaskContextFactory {
 | 
				
			|||||||
  public async createContextForDescription(): Promise<IIterativeContextResult> {
 | 
					  public async createContextForDescription(): Promise<IIterativeContextResult> {
 | 
				
			||||||
    const iterativeBuilder = new IterativeContextBuilder(
 | 
					    const iterativeBuilder = new IterativeContextBuilder(
 | 
				
			||||||
      this.projectDir,
 | 
					      this.projectDir,
 | 
				
			||||||
      this.configManager.getIterativeConfig()
 | 
					      this.configManager.getIterativeConfig(),
 | 
				
			||||||
 | 
					      this.openaiInstance
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    await iterativeBuilder.initialize();
 | 
					    await iterativeBuilder.initialize();
 | 
				
			||||||
    return await iterativeBuilder.buildContextIteratively('description');
 | 
					    return await iterativeBuilder.buildContextIteratively('description');
 | 
				
			||||||
@@ -52,16 +57,16 @@ export class TaskContextFactory {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Create context for commit message generation
 | 
					   * Create context for commit message generation
 | 
				
			||||||
   * @param gitDiff Optional git diff to include (currently not used in iterative mode)
 | 
					   * @param gitDiff Optional git diff to include in the context
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  public async createContextForCommit(gitDiff?: string): Promise<IIterativeContextResult> {
 | 
					  public async createContextForCommit(gitDiff?: string): Promise<IIterativeContextResult> {
 | 
				
			||||||
    const iterativeBuilder = new IterativeContextBuilder(
 | 
					    const iterativeBuilder = new IterativeContextBuilder(
 | 
				
			||||||
      this.projectDir,
 | 
					      this.projectDir,
 | 
				
			||||||
      this.configManager.getIterativeConfig()
 | 
					      this.configManager.getIterativeConfig(),
 | 
				
			||||||
 | 
					      this.openaiInstance
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    await iterativeBuilder.initialize();
 | 
					    await iterativeBuilder.initialize();
 | 
				
			||||||
    // Note: git diff could be incorporated into the iterative prompts if needed
 | 
					    return await iterativeBuilder.buildContextIteratively('commit', gitDiff);
 | 
				
			||||||
    return await iterativeBuilder.buildContextIteratively('commit');
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user