feat(context): Introduce smart context system: analyzer, lazy loader, cache and README/docs improvements
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import type { IContextConfig, ITrimConfig, ITaskConfig, TaskType, ContextMode } from './types.js';
|
||||
import * as fs from 'fs';
|
||||
import type {
|
||||
IContextConfig,
|
||||
ITrimConfig,
|
||||
ITaskConfig,
|
||||
TaskType,
|
||||
ContextMode,
|
||||
ICacheConfig,
|
||||
IAnalyzerConfig,
|
||||
IPrioritizationWeights,
|
||||
ITierConfig
|
||||
} from './types.js';
|
||||
|
||||
/**
|
||||
* Manages configuration for context building
|
||||
@@ -8,6 +19,7 @@ export class ConfigManager {
|
||||
private static instance: ConfigManager;
|
||||
private config: IContextConfig;
|
||||
private projectDir: string = '';
|
||||
private configCache: { mtime: number; config: IContextConfig } | null = null;
|
||||
|
||||
/**
|
||||
* Get the singleton instance of ConfigManager
|
||||
@@ -65,6 +77,28 @@ export class ConfigManager {
|
||||
maxFunctionLines: 5,
|
||||
removeComments: true,
|
||||
removeBlankLines: true
|
||||
},
|
||||
cache: {
|
||||
enabled: true,
|
||||
ttl: 3600, // 1 hour
|
||||
maxSize: 100, // 100MB
|
||||
directory: undefined // Will be set to .nogit/context-cache by ContextCache
|
||||
},
|
||||
analyzer: {
|
||||
enabled: true,
|
||||
useAIRefinement: false, // Disabled by default for now
|
||||
aiModel: 'haiku'
|
||||
},
|
||||
prioritization: {
|
||||
dependencyWeight: 0.3,
|
||||
relevanceWeight: 0.4,
|
||||
efficiencyWeight: 0.2,
|
||||
recencyWeight: 0.1
|
||||
},
|
||||
tiers: {
|
||||
essential: { minScore: 0.8, trimLevel: 'none' },
|
||||
important: { minScore: 0.5, trimLevel: 'light' },
|
||||
optional: { minScore: 0.2, trimLevel: 'aggressive' }
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -77,21 +111,40 @@ export class ConfigManager {
|
||||
if (!this.projectDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create KeyValueStore for this project
|
||||
// We'll just use smartfile directly instead of KeyValueStore
|
||||
|
||||
|
||||
const npmextraJsonPath = plugins.path.join(this.projectDir, 'npmextra.json');
|
||||
|
||||
// Check if file exists
|
||||
const fileExists = await plugins.smartfile.fs.fileExists(npmextraJsonPath);
|
||||
if (!fileExists) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check cache
|
||||
const stats = await fs.promises.stat(npmextraJsonPath);
|
||||
const currentMtime = Math.floor(stats.mtimeMs);
|
||||
|
||||
if (this.configCache && this.configCache.mtime === currentMtime) {
|
||||
// Use cached config
|
||||
this.config = this.configCache.config;
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the npmextra.json file
|
||||
const npmextraJsonFile = await plugins.smartfile.SmartFile.fromFilePath(
|
||||
plugins.path.join(this.projectDir, 'npmextra.json')
|
||||
);
|
||||
const npmextraJsonFile = await plugins.smartfile.SmartFile.fromFilePath(npmextraJsonPath);
|
||||
const npmextraContent = JSON.parse(npmextraJsonFile.contents.toString());
|
||||
|
||||
|
||||
// Check for tsdoc context configuration
|
||||
if (npmextraContent?.tsdoc?.context) {
|
||||
// Merge with default config
|
||||
this.config = this.mergeConfigs(this.config, npmextraContent.tsdoc.context);
|
||||
}
|
||||
|
||||
// Cache the config
|
||||
this.configCache = {
|
||||
mtime: currentMtime,
|
||||
config: { ...this.config }
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error loading context configuration:', error);
|
||||
}
|
||||
@@ -131,7 +184,39 @@ export class ConfigManager {
|
||||
...userConfig.trimming
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Merge cache configuration
|
||||
if (userConfig.cache) {
|
||||
result.cache = {
|
||||
...result.cache,
|
||||
...userConfig.cache
|
||||
};
|
||||
}
|
||||
|
||||
// Merge analyzer configuration
|
||||
if (userConfig.analyzer) {
|
||||
result.analyzer = {
|
||||
...result.analyzer,
|
||||
...userConfig.analyzer
|
||||
};
|
||||
}
|
||||
|
||||
// Merge prioritization weights
|
||||
if (userConfig.prioritization) {
|
||||
result.prioritization = {
|
||||
...result.prioritization,
|
||||
...userConfig.prioritization
|
||||
};
|
||||
}
|
||||
|
||||
// Merge tier configuration
|
||||
if (userConfig.tiers) {
|
||||
result.tiers = {
|
||||
...result.tiers,
|
||||
...userConfig.tiers
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -179,26 +264,29 @@ export class ConfigManager {
|
||||
public async updateConfig(config: Partial<IContextConfig>): Promise<void> {
|
||||
// Merge with existing config
|
||||
this.config = this.mergeConfigs(this.config, config);
|
||||
|
||||
|
||||
// Invalidate cache
|
||||
this.configCache = null;
|
||||
|
||||
try {
|
||||
if (!this.projectDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Read the existing npmextra.json file
|
||||
const npmextraJsonPath = plugins.path.join(this.projectDir, 'npmextra.json');
|
||||
let npmextraContent = {};
|
||||
|
||||
|
||||
if (await plugins.smartfile.fs.fileExists(npmextraJsonPath)) {
|
||||
const npmextraJsonFile = await plugins.smartfile.SmartFile.fromFilePath(npmextraJsonPath);
|
||||
npmextraContent = JSON.parse(npmextraJsonFile.contents.toString()) || {};
|
||||
}
|
||||
|
||||
|
||||
// Update the tsdoc context configuration
|
||||
const typedContent = npmextraContent as any;
|
||||
if (!typedContent.tsdoc) typedContent.tsdoc = {};
|
||||
typedContent.tsdoc.context = this.config;
|
||||
|
||||
|
||||
// Write back to npmextra.json
|
||||
const updatedContent = JSON.stringify(npmextraContent, null, 2);
|
||||
await plugins.smartfile.memory.toFs(updatedContent, npmextraJsonPath);
|
||||
@@ -206,4 +294,48 @@ export class ConfigManager {
|
||||
console.error('Error updating context configuration:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache configuration
|
||||
*/
|
||||
public getCacheConfig(): ICacheConfig {
|
||||
return this.config.cache || { enabled: true, ttl: 3600, maxSize: 100 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get analyzer configuration
|
||||
*/
|
||||
public getAnalyzerConfig(): IAnalyzerConfig {
|
||||
return this.config.analyzer || { enabled: true, useAIRefinement: false, aiModel: 'haiku' };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prioritization weights
|
||||
*/
|
||||
public getPrioritizationWeights(): IPrioritizationWeights {
|
||||
return this.config.prioritization || {
|
||||
dependencyWeight: 0.3,
|
||||
relevanceWeight: 0.4,
|
||||
efficiencyWeight: 0.2,
|
||||
recencyWeight: 0.1
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tier configuration
|
||||
*/
|
||||
public getTierConfig(): ITierConfig {
|
||||
return this.config.tiers || {
|
||||
essential: { minScore: 0.8, trimLevel: 'none' },
|
||||
important: { minScore: 0.5, trimLevel: 'light' },
|
||||
optional: { minScore: 0.2, trimLevel: 'aggressive' }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the config cache (force reload on next access)
|
||||
*/
|
||||
public clearCache(): void {
|
||||
this.configCache = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user