feat(context): Wire OpenAI provider through task context factory and add git-diff support to iterative context builder

This commit is contained in:
2025-11-03 13:37:16 +00:00
parent a6d678e36c
commit ebc3d760af
7 changed files with 72 additions and 22 deletions

View File

@@ -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

View File

@@ -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.'
} }

View File

@@ -32,7 +32,10 @@ export class Commit {
'package-lock.json', 'package-lock.json',
]); ]);
// 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

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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');
} }
/** /**