209 lines
6.0 KiB
TypeScript
209 lines
6.0 KiB
TypeScript
import * as plugins from '../plugins.js';
|
|
import type { IContextConfig, ITrimConfig, ITaskConfig, TaskType, ContextMode } from './types.js';
|
|
|
|
/**
|
|
* Manages configuration for context building
|
|
*/
|
|
export class ConfigManager {
|
|
private static instance: ConfigManager;
|
|
private config: IContextConfig;
|
|
private projectDir: string = '';
|
|
|
|
/**
|
|
* Get the singleton instance of ConfigManager
|
|
*/
|
|
public static getInstance(): ConfigManager {
|
|
if (!ConfigManager.instance) {
|
|
ConfigManager.instance = new ConfigManager();
|
|
}
|
|
return ConfigManager.instance;
|
|
}
|
|
|
|
/**
|
|
* Private constructor for singleton pattern
|
|
*/
|
|
private constructor() {
|
|
this.config = this.getDefaultConfig();
|
|
}
|
|
|
|
/**
|
|
* Initialize the config manager with a project directory
|
|
* @param projectDir The project directory
|
|
*/
|
|
public async initialize(projectDir: string): Promise<void> {
|
|
this.projectDir = projectDir;
|
|
await this.loadConfig();
|
|
}
|
|
|
|
/**
|
|
* Get the default configuration
|
|
*/
|
|
private getDefaultConfig(): IContextConfig {
|
|
return {
|
|
maxTokens: 190000, // Default for o4-mini with some buffer
|
|
defaultMode: 'trimmed',
|
|
taskSpecificSettings: {
|
|
readme: {
|
|
mode: 'trimmed',
|
|
includePaths: ['ts/', 'src/'],
|
|
excludePaths: ['test/', 'node_modules/']
|
|
},
|
|
commit: {
|
|
mode: 'trimmed',
|
|
focusOnChangedFiles: true
|
|
},
|
|
description: {
|
|
mode: 'trimmed',
|
|
includePackageInfo: true
|
|
}
|
|
},
|
|
trimming: {
|
|
removeImplementations: true,
|
|
preserveInterfaces: true,
|
|
preserveTypeDefs: true,
|
|
preserveJSDoc: true,
|
|
maxFunctionLines: 5,
|
|
removeComments: true,
|
|
removeBlankLines: true
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Load configuration from npmextra.json
|
|
*/
|
|
private async loadConfig(): Promise<void> {
|
|
try {
|
|
if (!this.projectDir) {
|
|
return;
|
|
}
|
|
|
|
// Create KeyValueStore for this project
|
|
// We'll just use smartfile directly instead of KeyValueStore
|
|
|
|
// Read the npmextra.json file
|
|
const npmextraJsonFile = await plugins.smartfile.SmartFile.fromFilePath(
|
|
plugins.path.join(this.projectDir, 'npmextra.json')
|
|
);
|
|
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);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading context configuration:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Merge configurations, with userConfig taking precedence
|
|
* @param defaultConfig The default configuration
|
|
* @param userConfig The user configuration
|
|
*/
|
|
private mergeConfigs(defaultConfig: IContextConfig, userConfig: Partial<IContextConfig>): IContextConfig {
|
|
const result: IContextConfig = { ...defaultConfig };
|
|
|
|
// Merge top-level properties
|
|
if (userConfig.maxTokens !== undefined) result.maxTokens = userConfig.maxTokens;
|
|
if (userConfig.defaultMode !== undefined) result.defaultMode = userConfig.defaultMode;
|
|
|
|
// Merge task-specific settings
|
|
if (userConfig.taskSpecificSettings) {
|
|
result.taskSpecificSettings = result.taskSpecificSettings || {};
|
|
|
|
// For each task type, merge settings
|
|
(['readme', 'commit', 'description'] as TaskType[]).forEach(taskType => {
|
|
if (userConfig.taskSpecificSettings?.[taskType]) {
|
|
result.taskSpecificSettings![taskType] = {
|
|
...result.taskSpecificSettings![taskType],
|
|
...userConfig.taskSpecificSettings[taskType]
|
|
};
|
|
}
|
|
});
|
|
}
|
|
|
|
// Merge trimming configuration
|
|
if (userConfig.trimming) {
|
|
result.trimming = {
|
|
...result.trimming,
|
|
...userConfig.trimming
|
|
};
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get the complete configuration
|
|
*/
|
|
public getConfig(): IContextConfig {
|
|
return this.config;
|
|
}
|
|
|
|
/**
|
|
* Get the trimming configuration
|
|
*/
|
|
public getTrimConfig(): ITrimConfig {
|
|
return this.config.trimming || {};
|
|
}
|
|
|
|
/**
|
|
* Get configuration for a specific task
|
|
* @param taskType The type of task
|
|
*/
|
|
public getTaskConfig(taskType: TaskType): ITaskConfig {
|
|
// Get task-specific config or empty object
|
|
const taskConfig = this.config.taskSpecificSettings?.[taskType] || {};
|
|
|
|
// If mode is not specified, use default mode
|
|
if (!taskConfig.mode) {
|
|
taskConfig.mode = this.config.defaultMode;
|
|
}
|
|
|
|
return taskConfig;
|
|
}
|
|
|
|
/**
|
|
* Get the maximum tokens allowed for context
|
|
*/
|
|
public getMaxTokens(): number {
|
|
return this.config.maxTokens || 190000;
|
|
}
|
|
|
|
/**
|
|
* Update the configuration
|
|
* @param config The new configuration
|
|
*/
|
|
public async updateConfig(config: Partial<IContextConfig>): Promise<void> {
|
|
// Merge with existing config
|
|
this.config = this.mergeConfigs(this.config, config);
|
|
|
|
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);
|
|
} catch (error) {
|
|
console.error('Error updating context configuration:', error);
|
|
}
|
|
}
|
|
} |