feat: create tm-core and apps/cli (#1093)
- add typescript - add npm workspaces
This commit is contained in:
423
packages/tm-core/src/interfaces/ai-provider.interface.ts
Normal file
423
packages/tm-core/src/interfaces/ai-provider.interface.ts
Normal file
@@ -0,0 +1,423 @@
|
||||
/**
|
||||
* @fileoverview AI Provider interface definitions for the tm-core package
|
||||
* This file defines the contract for all AI provider implementations
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for AI completion requests
|
||||
*/
|
||||
export interface AIOptions {
|
||||
/** Temperature for response randomness (0.0 to 1.0) */
|
||||
temperature?: number;
|
||||
/** Maximum number of tokens to generate */
|
||||
maxTokens?: number;
|
||||
/** Whether to use streaming responses */
|
||||
stream?: boolean;
|
||||
/** Top-p sampling parameter (0.0 to 1.0) */
|
||||
topP?: number;
|
||||
/** Frequency penalty to reduce repetition (-2.0 to 2.0) */
|
||||
frequencyPenalty?: number;
|
||||
/** Presence penalty to encourage new topics (-2.0 to 2.0) */
|
||||
presencePenalty?: number;
|
||||
/** Stop sequences to halt generation */
|
||||
stop?: string | string[];
|
||||
/** Custom system prompt override */
|
||||
systemPrompt?: string;
|
||||
/** Request timeout in milliseconds */
|
||||
timeout?: number;
|
||||
/** Number of retry attempts on failure */
|
||||
retries?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response from AI completion request
|
||||
*/
|
||||
export interface AIResponse {
|
||||
/** Generated text content */
|
||||
content: string;
|
||||
/** Token count for the request */
|
||||
inputTokens: number;
|
||||
/** Token count for the response */
|
||||
outputTokens: number;
|
||||
/** Total tokens used */
|
||||
totalTokens: number;
|
||||
/** Cost in USD (if available) */
|
||||
cost?: number;
|
||||
/** Model used for generation */
|
||||
model: string;
|
||||
/** Provider name */
|
||||
provider: string;
|
||||
/** Response timestamp */
|
||||
timestamp: string;
|
||||
/** Request duration in milliseconds */
|
||||
duration: number;
|
||||
/** Whether the response was cached */
|
||||
cached?: boolean;
|
||||
/** Finish reason (completed, length, stop, etc.) */
|
||||
finishReason?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* AI model information
|
||||
*/
|
||||
export interface AIModel {
|
||||
/** Model identifier */
|
||||
id: string;
|
||||
/** Human-readable model name */
|
||||
name: string;
|
||||
/** Model description */
|
||||
description?: string;
|
||||
/** Maximum context length in tokens */
|
||||
contextLength: number;
|
||||
/** Input cost per 1K tokens in USD */
|
||||
inputCostPer1K?: number;
|
||||
/** Output cost per 1K tokens in USD */
|
||||
outputCostPer1K?: number;
|
||||
/** Whether the model supports function calling */
|
||||
supportsFunctions?: boolean;
|
||||
/** Whether the model supports vision/image inputs */
|
||||
supportsVision?: boolean;
|
||||
/** Whether the model supports streaming */
|
||||
supportsStreaming?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider capabilities and metadata
|
||||
*/
|
||||
export interface ProviderInfo {
|
||||
/** Provider name */
|
||||
name: string;
|
||||
/** Provider display name */
|
||||
displayName: string;
|
||||
/** Provider description */
|
||||
description?: string;
|
||||
/** Base API URL */
|
||||
baseUrl?: string;
|
||||
/** Available models */
|
||||
models: AIModel[];
|
||||
/** Default model ID */
|
||||
defaultModel: string;
|
||||
/** Whether the provider requires an API key */
|
||||
requiresApiKey: boolean;
|
||||
/** Supported features */
|
||||
features: {
|
||||
streaming?: boolean;
|
||||
functions?: boolean;
|
||||
vision?: boolean;
|
||||
embeddings?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for AI provider implementations
|
||||
* All AI providers must implement this interface
|
||||
*/
|
||||
export interface IAIProvider {
|
||||
/**
|
||||
* Generate a text completion from a prompt
|
||||
* @param prompt - Input prompt text
|
||||
* @param options - Optional generation parameters
|
||||
* @returns Promise that resolves to AI response
|
||||
*/
|
||||
generateCompletion(prompt: string, options?: AIOptions): Promise<AIResponse>;
|
||||
|
||||
/**
|
||||
* Generate a streaming completion (if supported)
|
||||
* @param prompt - Input prompt text
|
||||
* @param options - Optional generation parameters
|
||||
* @returns AsyncIterator of response chunks
|
||||
*/
|
||||
generateStreamingCompletion(
|
||||
prompt: string,
|
||||
options?: AIOptions
|
||||
): AsyncIterator<Partial<AIResponse>>;
|
||||
|
||||
/**
|
||||
* Calculate token count for given text
|
||||
* @param text - Text to count tokens for
|
||||
* @param model - Optional model to use for counting
|
||||
* @returns Number of tokens
|
||||
*/
|
||||
calculateTokens(text: string, model?: string): number;
|
||||
|
||||
/**
|
||||
* Get the provider name
|
||||
* @returns Provider name string
|
||||
*/
|
||||
getName(): string;
|
||||
|
||||
/**
|
||||
* Get current model being used
|
||||
* @returns Current model ID
|
||||
*/
|
||||
getModel(): string;
|
||||
|
||||
/**
|
||||
* Set the model to use for requests
|
||||
* @param model - Model ID to use
|
||||
*/
|
||||
setModel(model: string): void;
|
||||
|
||||
/**
|
||||
* Get the default model for this provider
|
||||
* @returns Default model ID
|
||||
*/
|
||||
getDefaultModel(): string;
|
||||
|
||||
/**
|
||||
* Check if the provider is available and configured
|
||||
* @returns Promise that resolves to availability status
|
||||
*/
|
||||
isAvailable(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Get provider information and capabilities
|
||||
* @returns Provider information object
|
||||
*/
|
||||
getProviderInfo(): ProviderInfo;
|
||||
|
||||
/**
|
||||
* Get available models for this provider
|
||||
* @returns Array of available models
|
||||
*/
|
||||
getAvailableModels(): AIModel[];
|
||||
|
||||
/**
|
||||
* Validate API key or credentials
|
||||
* @returns Promise that resolves to validation status
|
||||
*/
|
||||
validateCredentials(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Get usage statistics if available
|
||||
* @returns Promise that resolves to usage stats or null
|
||||
*/
|
||||
getUsageStats(): Promise<ProviderUsageStats | null>;
|
||||
|
||||
/**
|
||||
* Initialize the provider (set up connections, validate config, etc.)
|
||||
* @returns Promise that resolves when initialization is complete
|
||||
*/
|
||||
initialize(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Clean up and close provider connections
|
||||
* @returns Promise that resolves when cleanup is complete
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage statistics for a provider
|
||||
*/
|
||||
export interface ProviderUsageStats {
|
||||
/** Total requests made */
|
||||
totalRequests: number;
|
||||
/** Total tokens consumed */
|
||||
totalTokens: number;
|
||||
/** Total cost in USD */
|
||||
totalCost: number;
|
||||
/** Requests today */
|
||||
requestsToday: number;
|
||||
/** Tokens used today */
|
||||
tokensToday: number;
|
||||
/** Cost today */
|
||||
costToday: number;
|
||||
/** Average response time in milliseconds */
|
||||
averageResponseTime: number;
|
||||
/** Success rate (0.0 to 1.0) */
|
||||
successRate: number;
|
||||
/** Last request timestamp */
|
||||
lastRequestAt?: string;
|
||||
/** Rate limit information if available */
|
||||
rateLimits?: {
|
||||
requestsPerMinute: number;
|
||||
tokensPerMinute: number;
|
||||
requestsRemaining: number;
|
||||
tokensRemaining: number;
|
||||
resetTime: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for AI provider instances
|
||||
*/
|
||||
export interface AIProviderConfig {
|
||||
/** API key for the provider */
|
||||
apiKey: string;
|
||||
/** Base URL override */
|
||||
baseUrl?: string;
|
||||
/** Default model to use */
|
||||
model?: string;
|
||||
/** Default generation options */
|
||||
defaultOptions?: AIOptions;
|
||||
/** Request timeout in milliseconds */
|
||||
timeout?: number;
|
||||
/** Maximum retry attempts */
|
||||
maxRetries?: number;
|
||||
/** Custom headers to include in requests */
|
||||
headers?: Record<string, string>;
|
||||
/** Enable request/response logging */
|
||||
enableLogging?: boolean;
|
||||
/** Enable usage tracking */
|
||||
enableUsageTracking?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for AI provider implementations
|
||||
* Provides common functionality and enforces the interface
|
||||
*/
|
||||
export abstract class BaseAIProvider implements IAIProvider {
|
||||
protected config: AIProviderConfig;
|
||||
protected currentModel: string;
|
||||
protected usageStats: ProviderUsageStats | null = null;
|
||||
|
||||
constructor(config: AIProviderConfig) {
|
||||
this.config = config;
|
||||
this.currentModel = config.model || this.getDefaultModel();
|
||||
|
||||
if (config.enableUsageTracking) {
|
||||
this.initializeUsageTracking();
|
||||
}
|
||||
}
|
||||
|
||||
// Abstract methods that must be implemented by concrete classes
|
||||
abstract generateCompletion(
|
||||
prompt: string,
|
||||
options?: AIOptions
|
||||
): Promise<AIResponse>;
|
||||
abstract generateStreamingCompletion(
|
||||
prompt: string,
|
||||
options?: AIOptions
|
||||
): AsyncIterator<Partial<AIResponse>>;
|
||||
abstract calculateTokens(text: string, model?: string): number;
|
||||
abstract getName(): string;
|
||||
abstract getDefaultModel(): string;
|
||||
abstract isAvailable(): Promise<boolean>;
|
||||
abstract getProviderInfo(): ProviderInfo;
|
||||
abstract validateCredentials(): Promise<boolean>;
|
||||
abstract initialize(): Promise<void>;
|
||||
abstract close(): Promise<void>;
|
||||
|
||||
// Implemented methods with common functionality
|
||||
getModel(): string {
|
||||
return this.currentModel;
|
||||
}
|
||||
|
||||
setModel(model: string): void {
|
||||
const availableModels = this.getAvailableModels();
|
||||
const modelExists = availableModels.some((m) => m.id === model);
|
||||
|
||||
if (!modelExists) {
|
||||
throw new Error(
|
||||
`Model "${model}" is not available for provider "${this.getName()}"`
|
||||
);
|
||||
}
|
||||
|
||||
this.currentModel = model;
|
||||
}
|
||||
|
||||
getAvailableModels(): AIModel[] {
|
||||
return this.getProviderInfo().models;
|
||||
}
|
||||
|
||||
async getUsageStats(): Promise<ProviderUsageStats | null> {
|
||||
return this.usageStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize usage tracking
|
||||
*/
|
||||
protected initializeUsageTracking(): void {
|
||||
this.usageStats = {
|
||||
totalRequests: 0,
|
||||
totalTokens: 0,
|
||||
totalCost: 0,
|
||||
requestsToday: 0,
|
||||
tokensToday: 0,
|
||||
costToday: 0,
|
||||
averageResponseTime: 0,
|
||||
successRate: 1.0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update usage statistics after a request
|
||||
* @param response - AI response to record
|
||||
* @param duration - Request duration in milliseconds
|
||||
* @param success - Whether the request was successful
|
||||
*/
|
||||
protected updateUsageStats(
|
||||
response: AIResponse,
|
||||
duration: number,
|
||||
success: boolean
|
||||
): void {
|
||||
if (!this.usageStats) return;
|
||||
|
||||
this.usageStats.totalRequests++;
|
||||
this.usageStats.totalTokens += response.totalTokens;
|
||||
|
||||
if (response.cost) {
|
||||
this.usageStats.totalCost += response.cost;
|
||||
}
|
||||
|
||||
// Update daily stats (simplified - would need proper date tracking)
|
||||
this.usageStats.requestsToday++;
|
||||
this.usageStats.tokensToday += response.totalTokens;
|
||||
|
||||
if (response.cost) {
|
||||
this.usageStats.costToday += response.cost;
|
||||
}
|
||||
|
||||
// Update average response time
|
||||
const totalTime =
|
||||
this.usageStats.averageResponseTime * (this.usageStats.totalRequests - 1);
|
||||
this.usageStats.averageResponseTime =
|
||||
(totalTime + duration) / this.usageStats.totalRequests;
|
||||
|
||||
// Update success rate
|
||||
const successCount = Math.floor(
|
||||
this.usageStats.successRate * (this.usageStats.totalRequests - 1)
|
||||
);
|
||||
const newSuccessCount = successCount + (success ? 1 : 0);
|
||||
this.usageStats.successRate =
|
||||
newSuccessCount / this.usageStats.totalRequests;
|
||||
|
||||
this.usageStats.lastRequestAt = new Date().toISOString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge user options with default options
|
||||
* @param userOptions - User-provided options
|
||||
* @returns Merged options object
|
||||
*/
|
||||
protected mergeOptions(userOptions?: AIOptions): AIOptions {
|
||||
return {
|
||||
temperature: 0.7,
|
||||
maxTokens: 2000,
|
||||
stream: false,
|
||||
topP: 1.0,
|
||||
frequencyPenalty: 0.0,
|
||||
presencePenalty: 0.0,
|
||||
timeout: 30000,
|
||||
retries: 3,
|
||||
...this.config.defaultOptions,
|
||||
...userOptions
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate prompt input
|
||||
* @param prompt - Prompt to validate
|
||||
* @throws Error if prompt is invalid
|
||||
*/
|
||||
protected validatePrompt(prompt: string): void {
|
||||
if (!prompt || typeof prompt !== 'string') {
|
||||
throw new Error('Prompt must be a non-empty string');
|
||||
}
|
||||
|
||||
if (prompt.trim().length === 0) {
|
||||
throw new Error('Prompt cannot be empty or only whitespace');
|
||||
}
|
||||
}
|
||||
}
|
||||
413
packages/tm-core/src/interfaces/configuration.interface.ts
Normal file
413
packages/tm-core/src/interfaces/configuration.interface.ts
Normal file
@@ -0,0 +1,413 @@
|
||||
/**
|
||||
* @fileoverview Configuration interface definitions for the tm-core package
|
||||
* This file defines the contract for configuration management
|
||||
*/
|
||||
|
||||
import type { TaskComplexity, TaskPriority } from '../types/index';
|
||||
|
||||
/**
|
||||
* Model configuration for different AI roles
|
||||
*/
|
||||
export interface ModelConfig {
|
||||
/** Primary model for task generation and updates */
|
||||
main: string;
|
||||
/** Research model for enhanced task analysis (optional) */
|
||||
research?: string;
|
||||
/** Fallback model when primary fails */
|
||||
fallback: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* AI provider configuration
|
||||
*/
|
||||
export interface ProviderConfig {
|
||||
/** Provider name (e.g., 'anthropic', 'openai', 'perplexity') */
|
||||
name: string;
|
||||
/** API key for the provider */
|
||||
apiKey?: string;
|
||||
/** Base URL override */
|
||||
baseUrl?: string;
|
||||
/** Custom configuration options */
|
||||
options?: Record<string, unknown>;
|
||||
/** Whether this provider is enabled */
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Task generation and management settings
|
||||
*/
|
||||
export interface TaskSettings {
|
||||
/** Default priority for new tasks */
|
||||
defaultPriority: TaskPriority;
|
||||
/** Default complexity for analysis */
|
||||
defaultComplexity: TaskComplexity;
|
||||
/** Maximum number of subtasks per task */
|
||||
maxSubtasks: number;
|
||||
/** Maximum number of concurrent tasks */
|
||||
maxConcurrentTasks: number;
|
||||
/** Enable automatic task ID generation */
|
||||
autoGenerateIds: boolean;
|
||||
/** Task ID prefix (e.g., 'TASK-', 'TM-') */
|
||||
taskIdPrefix?: string;
|
||||
/** Enable task dependency validation */
|
||||
validateDependencies: boolean;
|
||||
/** Enable automatic timestamps */
|
||||
enableTimestamps: boolean;
|
||||
/** Enable effort tracking */
|
||||
enableEffortTracking: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag and context management settings
|
||||
*/
|
||||
export interface TagSettings {
|
||||
/** Enable tag-based task organization */
|
||||
enableTags: boolean;
|
||||
/** Default tag for new tasks */
|
||||
defaultTag: string;
|
||||
/** Maximum number of tags per task */
|
||||
maxTagsPerTask: number;
|
||||
/** Enable automatic tag creation from Git branches */
|
||||
autoCreateFromBranch: boolean;
|
||||
/** Tag naming convention (kebab-case, camelCase, snake_case) */
|
||||
tagNamingConvention: 'kebab-case' | 'camelCase' | 'snake_case';
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage and persistence settings
|
||||
*/
|
||||
export interface StorageSettings {
|
||||
/** Storage backend type */
|
||||
type: 'file' | 'api';
|
||||
/** Base path for file storage */
|
||||
basePath?: string;
|
||||
/** API endpoint for API storage (Hamster integration) */
|
||||
apiEndpoint?: string;
|
||||
/** Access token for API authentication */
|
||||
apiAccessToken?: string;
|
||||
/** Enable automatic backups */
|
||||
enableBackup: boolean;
|
||||
/** Maximum number of backups to retain */
|
||||
maxBackups: number;
|
||||
/** Enable compression for storage */
|
||||
enableCompression: boolean;
|
||||
/** File encoding for text files */
|
||||
encoding: BufferEncoding;
|
||||
/** Enable atomic file operations */
|
||||
atomicOperations: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry and resilience settings
|
||||
*/
|
||||
export interface RetrySettings {
|
||||
/** Number of retry attempts for failed operations */
|
||||
retryAttempts: number;
|
||||
/** Base delay between retries in milliseconds */
|
||||
retryDelay: number;
|
||||
/** Maximum delay between retries in milliseconds */
|
||||
maxRetryDelay: number;
|
||||
/** Exponential backoff multiplier */
|
||||
backoffMultiplier: number;
|
||||
/** Request timeout in milliseconds */
|
||||
requestTimeout: number;
|
||||
/** Enable retry for network errors */
|
||||
retryOnNetworkError: boolean;
|
||||
/** Enable retry for rate limit errors */
|
||||
retryOnRateLimit: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logging and debugging settings
|
||||
*/
|
||||
export interface LoggingSettings {
|
||||
/** Enable logging */
|
||||
enabled: boolean;
|
||||
/** Log level (error, warn, info, debug) */
|
||||
level: 'error' | 'warn' | 'info' | 'debug';
|
||||
/** Log file path (optional) */
|
||||
filePath?: string;
|
||||
/** Enable request/response logging */
|
||||
logRequests: boolean;
|
||||
/** Enable performance metrics logging */
|
||||
logPerformance: boolean;
|
||||
/** Enable error stack traces */
|
||||
logStackTraces: boolean;
|
||||
/** Maximum log file size in MB */
|
||||
maxFileSize: number;
|
||||
/** Maximum number of log files to retain */
|
||||
maxFiles: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security and validation settings
|
||||
*/
|
||||
export interface SecuritySettings {
|
||||
/** Enable API key validation */
|
||||
validateApiKeys: boolean;
|
||||
/** Enable request rate limiting */
|
||||
enableRateLimit: boolean;
|
||||
/** Maximum requests per minute */
|
||||
maxRequestsPerMinute: number;
|
||||
/** Enable input sanitization */
|
||||
sanitizeInputs: boolean;
|
||||
/** Maximum prompt length in characters */
|
||||
maxPromptLength: number;
|
||||
/** Allowed file extensions for imports */
|
||||
allowedFileExtensions: string[];
|
||||
/** Enable CORS protection */
|
||||
enableCors: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main configuration interface for Task Master core
|
||||
*/
|
||||
export interface IConfiguration {
|
||||
/** Project root path */
|
||||
projectPath: string;
|
||||
|
||||
/** Current AI provider name */
|
||||
aiProvider: string;
|
||||
|
||||
/** API keys for different providers */
|
||||
apiKeys: Record<string, string>;
|
||||
|
||||
/** Model configuration for different roles */
|
||||
models: ModelConfig;
|
||||
|
||||
/** Provider configurations */
|
||||
providers: Record<string, ProviderConfig>;
|
||||
|
||||
/** Task management settings */
|
||||
tasks: TaskSettings;
|
||||
|
||||
/** Tag and context settings */
|
||||
tags: TagSettings;
|
||||
|
||||
/** Storage configuration */
|
||||
storage: StorageSettings;
|
||||
|
||||
/** Retry and resilience settings */
|
||||
retry: RetrySettings;
|
||||
|
||||
/** Logging configuration */
|
||||
logging: LoggingSettings;
|
||||
|
||||
/** Security settings */
|
||||
security: SecuritySettings;
|
||||
|
||||
/** Custom user-defined settings */
|
||||
custom?: Record<string, unknown>;
|
||||
|
||||
/** Configuration version for migration purposes */
|
||||
version: string;
|
||||
|
||||
/** Last updated timestamp */
|
||||
lastUpdated: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial configuration for updates (all fields optional)
|
||||
*/
|
||||
export type PartialConfiguration = Partial<IConfiguration>;
|
||||
|
||||
/**
|
||||
* Configuration validation result
|
||||
*/
|
||||
export interface ConfigValidationResult {
|
||||
/** Whether the configuration is valid */
|
||||
isValid: boolean;
|
||||
/** Array of error messages */
|
||||
errors: string[];
|
||||
/** Array of warning messages */
|
||||
warnings: string[];
|
||||
/** Suggested fixes */
|
||||
suggestions?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Environment variable configuration mapping
|
||||
*/
|
||||
export interface EnvironmentConfig {
|
||||
/** Mapping of environment variables to config paths */
|
||||
variables: Record<string, string>;
|
||||
/** Prefix for environment variables */
|
||||
prefix: string;
|
||||
/** Whether to override existing config with env vars */
|
||||
override: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration schema definition for validation
|
||||
*/
|
||||
export interface ConfigSchema {
|
||||
/** Schema for the main configuration */
|
||||
properties: Record<string, ConfigProperty>;
|
||||
/** Required properties */
|
||||
required: string[];
|
||||
/** Additional properties allowed */
|
||||
additionalProperties: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration property schema
|
||||
*/
|
||||
export interface ConfigProperty {
|
||||
/** Property type */
|
||||
type: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
||||
/** Property description */
|
||||
description?: string;
|
||||
/** Default value */
|
||||
default?: unknown;
|
||||
/** Allowed values for enums */
|
||||
enum?: unknown[];
|
||||
/** Minimum value (for numbers) */
|
||||
minimum?: number;
|
||||
/** Maximum value (for numbers) */
|
||||
maximum?: number;
|
||||
/** Pattern for string validation */
|
||||
pattern?: string;
|
||||
/** Nested properties (for objects) */
|
||||
properties?: Record<string, ConfigProperty>;
|
||||
/** Array item type (for arrays) */
|
||||
items?: ConfigProperty;
|
||||
/** Whether the property is required */
|
||||
required?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default configuration factory
|
||||
*/
|
||||
export interface IConfigurationFactory {
|
||||
/**
|
||||
* Create a default configuration
|
||||
* @param projectPath - Project root path
|
||||
* @returns Default configuration object
|
||||
*/
|
||||
createDefault(projectPath: string): IConfiguration;
|
||||
|
||||
/**
|
||||
* Merge configurations with precedence
|
||||
* @param base - Base configuration
|
||||
* @param override - Override configuration
|
||||
* @returns Merged configuration
|
||||
*/
|
||||
merge(base: IConfiguration, override: PartialConfiguration): IConfiguration;
|
||||
|
||||
/**
|
||||
* Validate configuration against schema
|
||||
* @param config - Configuration to validate
|
||||
* @returns Validation result
|
||||
*/
|
||||
validate(config: IConfiguration): ConfigValidationResult;
|
||||
|
||||
/**
|
||||
* Load configuration from environment variables
|
||||
* @param envConfig - Environment variable mapping
|
||||
* @returns Partial configuration from environment
|
||||
*/
|
||||
loadFromEnvironment(envConfig: EnvironmentConfig): PartialConfiguration;
|
||||
|
||||
/**
|
||||
* Get configuration schema
|
||||
* @returns Configuration schema definition
|
||||
*/
|
||||
getSchema(): ConfigSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration manager interface
|
||||
*/
|
||||
export interface IConfigurationManager {
|
||||
/**
|
||||
* Load configuration from file or create default
|
||||
* @param configPath - Path to configuration file
|
||||
* @returns Promise that resolves to configuration
|
||||
*/
|
||||
load(configPath?: string): Promise<IConfiguration>;
|
||||
|
||||
/**
|
||||
* Save configuration to file
|
||||
* @param config - Configuration to save
|
||||
* @param configPath - Optional path override
|
||||
* @returns Promise that resolves when save is complete
|
||||
*/
|
||||
save(config: IConfiguration, configPath?: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Update configuration with partial changes
|
||||
* @param updates - Partial configuration updates
|
||||
* @returns Promise that resolves to updated configuration
|
||||
*/
|
||||
update(updates: PartialConfiguration): Promise<IConfiguration>;
|
||||
|
||||
/**
|
||||
* Get current configuration
|
||||
* @returns Current configuration object
|
||||
*/
|
||||
getConfig(): IConfiguration;
|
||||
|
||||
/**
|
||||
* Watch for configuration changes
|
||||
* @param callback - Function to call when config changes
|
||||
* @returns Function to stop watching
|
||||
*/
|
||||
watch(callback: (config: IConfiguration) => void): () => void;
|
||||
|
||||
/**
|
||||
* Validate current configuration
|
||||
* @returns Validation result
|
||||
*/
|
||||
validate(): ConfigValidationResult;
|
||||
|
||||
/**
|
||||
* Reset configuration to defaults
|
||||
* @returns Promise that resolves when reset is complete
|
||||
*/
|
||||
reset(): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constants for default configuration values
|
||||
*/
|
||||
export const DEFAULT_CONFIG_VALUES = {
|
||||
MODELS: {
|
||||
MAIN: 'claude-3-5-sonnet-20241022',
|
||||
FALLBACK: 'gpt-4o-mini'
|
||||
},
|
||||
TASKS: {
|
||||
DEFAULT_PRIORITY: 'medium' as TaskPriority,
|
||||
DEFAULT_COMPLEXITY: 'moderate' as TaskComplexity,
|
||||
MAX_SUBTASKS: 20,
|
||||
MAX_CONCURRENT: 5,
|
||||
TASK_ID_PREFIX: 'TASK-'
|
||||
},
|
||||
TAGS: {
|
||||
DEFAULT_TAG: 'master',
|
||||
MAX_TAGS_PER_TASK: 10,
|
||||
NAMING_CONVENTION: 'kebab-case' as const
|
||||
},
|
||||
STORAGE: {
|
||||
TYPE: 'file' as const,
|
||||
ENCODING: 'utf8' as BufferEncoding,
|
||||
MAX_BACKUPS: 5
|
||||
},
|
||||
RETRY: {
|
||||
ATTEMPTS: 3,
|
||||
DELAY: 1000,
|
||||
MAX_DELAY: 30000,
|
||||
BACKOFF_MULTIPLIER: 2,
|
||||
TIMEOUT: 30000
|
||||
},
|
||||
LOGGING: {
|
||||
LEVEL: 'info' as const,
|
||||
MAX_FILE_SIZE: 10,
|
||||
MAX_FILES: 5
|
||||
},
|
||||
SECURITY: {
|
||||
MAX_REQUESTS_PER_MINUTE: 60,
|
||||
MAX_PROMPT_LENGTH: 100000,
|
||||
ALLOWED_EXTENSIONS: ['.txt', '.md', '.json']
|
||||
},
|
||||
VERSION: '1.0.0'
|
||||
} as const;
|
||||
16
packages/tm-core/src/interfaces/index.ts
Normal file
16
packages/tm-core/src/interfaces/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @fileoverview Interface definitions index for the tm-core package
|
||||
* This file exports all interface definitions from their respective modules
|
||||
*/
|
||||
|
||||
// Storage interfaces
|
||||
export type * from './storage.interface';
|
||||
export * from './storage.interface';
|
||||
|
||||
// AI Provider interfaces
|
||||
export type * from './ai-provider.interface';
|
||||
export * from './ai-provider.interface';
|
||||
|
||||
// Configuration interfaces
|
||||
export type * from './configuration.interface';
|
||||
export * from './configuration.interface';
|
||||
238
packages/tm-core/src/interfaces/storage.interface.ts
Normal file
238
packages/tm-core/src/interfaces/storage.interface.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @fileoverview Storage interface definitions for the tm-core package
|
||||
* This file defines the contract for all storage implementations
|
||||
*/
|
||||
|
||||
import type { Task, TaskMetadata } from '../types/index';
|
||||
|
||||
/**
|
||||
* Interface for storage operations on tasks
|
||||
* All storage implementations must implement this interface
|
||||
*/
|
||||
export interface IStorage {
|
||||
/**
|
||||
* Load all tasks from storage, optionally filtered by tag
|
||||
* @param tag - Optional tag to filter tasks by
|
||||
* @returns Promise that resolves to an array of tasks
|
||||
*/
|
||||
loadTasks(tag?: string): Promise<Task[]>;
|
||||
|
||||
/**
|
||||
* Save tasks to storage, replacing existing tasks
|
||||
* @param tasks - Array of tasks to save
|
||||
* @param tag - Optional tag context for the tasks
|
||||
* @returns Promise that resolves when save is complete
|
||||
*/
|
||||
saveTasks(tasks: Task[], tag?: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Append new tasks to existing storage without replacing
|
||||
* @param tasks - Array of tasks to append
|
||||
* @param tag - Optional tag context for the tasks
|
||||
* @returns Promise that resolves when append is complete
|
||||
*/
|
||||
appendTasks(tasks: Task[], tag?: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Update a specific task by ID
|
||||
* @param taskId - ID of the task to update
|
||||
* @param updates - Partial task object with fields to update
|
||||
* @param tag - Optional tag context for the task
|
||||
* @returns Promise that resolves when update is complete
|
||||
*/
|
||||
updateTask(
|
||||
taskId: string,
|
||||
updates: Partial<Task>,
|
||||
tag?: string
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete a task by ID
|
||||
* @param taskId - ID of the task to delete
|
||||
* @param tag - Optional tag context for the task
|
||||
* @returns Promise that resolves when deletion is complete
|
||||
*/
|
||||
deleteTask(taskId: string, tag?: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Check if tasks exist in storage for the given tag
|
||||
* @param tag - Optional tag to check existence for
|
||||
* @returns Promise that resolves to boolean indicating existence
|
||||
*/
|
||||
exists(tag?: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Load metadata about the task collection
|
||||
* @param tag - Optional tag to get metadata for
|
||||
* @returns Promise that resolves to task metadata
|
||||
*/
|
||||
loadMetadata(tag?: string): Promise<TaskMetadata | null>;
|
||||
|
||||
/**
|
||||
* Save metadata about the task collection
|
||||
* @param metadata - Metadata object to save
|
||||
* @param tag - Optional tag context for the metadata
|
||||
* @returns Promise that resolves when save is complete
|
||||
*/
|
||||
saveMetadata(metadata: TaskMetadata, tag?: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get all available tags in storage
|
||||
* @returns Promise that resolves to array of available tags
|
||||
*/
|
||||
getAllTags(): Promise<string[]>;
|
||||
|
||||
/**
|
||||
* Delete all tasks and metadata for a specific tag
|
||||
* @param tag - Tag to delete
|
||||
* @returns Promise that resolves when deletion is complete
|
||||
*/
|
||||
deleteTag(tag: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Rename a tag (move all tasks from old tag to new tag)
|
||||
* @param oldTag - Current tag name
|
||||
* @param newTag - New tag name
|
||||
* @returns Promise that resolves when rename is complete
|
||||
*/
|
||||
renameTag(oldTag: string, newTag: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Copy all tasks from one tag to another
|
||||
* @param sourceTag - Source tag to copy from
|
||||
* @param targetTag - Target tag to copy to
|
||||
* @returns Promise that resolves when copy is complete
|
||||
*/
|
||||
copyTag(sourceTag: string, targetTag: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Initialize storage (create necessary directories, files, etc.)
|
||||
* @returns Promise that resolves when initialization is complete
|
||||
*/
|
||||
initialize(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Clean up and close storage connections
|
||||
* @returns Promise that resolves when cleanup is complete
|
||||
*/
|
||||
close(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get storage statistics (file sizes, task counts, etc.)
|
||||
* @returns Promise that resolves to storage statistics
|
||||
*/
|
||||
getStats(): Promise<StorageStats>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage statistics interface
|
||||
*/
|
||||
export interface StorageStats {
|
||||
/** Total number of tasks across all tags */
|
||||
totalTasks: number;
|
||||
/** Total number of tags */
|
||||
totalTags: number;
|
||||
/** Storage size in bytes */
|
||||
storageSize: number;
|
||||
/** Last modified timestamp */
|
||||
lastModified: string;
|
||||
/** Available tags with task counts */
|
||||
tagStats: Array<{
|
||||
tag: string;
|
||||
taskCount: number;
|
||||
lastModified: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for storage implementations
|
||||
*/
|
||||
export interface StorageConfig {
|
||||
/** Base path for storage */
|
||||
basePath: string;
|
||||
/** Enable backup creation */
|
||||
enableBackup?: boolean;
|
||||
/** Maximum number of backups to keep */
|
||||
maxBackups?: number;
|
||||
/** Enable compression for storage */
|
||||
enableCompression?: boolean;
|
||||
/** File encoding (default: utf8) */
|
||||
encoding?: BufferEncoding;
|
||||
/** Enable atomic writes */
|
||||
atomicWrites?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base abstract class for storage implementations
|
||||
* Provides common functionality and enforces the interface
|
||||
*/
|
||||
export abstract class BaseStorage implements IStorage {
|
||||
protected config: StorageConfig;
|
||||
|
||||
constructor(config: StorageConfig) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
// Abstract methods that must be implemented by concrete classes
|
||||
abstract loadTasks(tag?: string): Promise<Task[]>;
|
||||
abstract saveTasks(tasks: Task[], tag?: string): Promise<void>;
|
||||
abstract appendTasks(tasks: Task[], tag?: string): Promise<void>;
|
||||
abstract updateTask(
|
||||
taskId: string,
|
||||
updates: Partial<Task>,
|
||||
tag?: string
|
||||
): Promise<void>;
|
||||
abstract deleteTask(taskId: string, tag?: string): Promise<void>;
|
||||
abstract exists(tag?: string): Promise<boolean>;
|
||||
abstract loadMetadata(tag?: string): Promise<TaskMetadata | null>;
|
||||
abstract saveMetadata(metadata: TaskMetadata, tag?: string): Promise<void>;
|
||||
abstract getAllTags(): Promise<string[]>;
|
||||
abstract deleteTag(tag: string): Promise<void>;
|
||||
abstract renameTag(oldTag: string, newTag: string): Promise<void>;
|
||||
abstract copyTag(sourceTag: string, targetTag: string): Promise<void>;
|
||||
abstract initialize(): Promise<void>;
|
||||
abstract close(): Promise<void>;
|
||||
abstract getStats(): Promise<StorageStats>;
|
||||
|
||||
/**
|
||||
* Utility method to generate backup filename
|
||||
* @param originalPath - Original file path
|
||||
* @returns Backup file path with timestamp
|
||||
*/
|
||||
protected generateBackupPath(originalPath: string): string {
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
const parts = originalPath.split('.');
|
||||
const extension = parts.pop();
|
||||
const baseName = parts.join('.');
|
||||
return `${baseName}.backup.${timestamp}.${extension}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to validate task data before storage operations
|
||||
* @param task - Task to validate
|
||||
* @throws Error if task is invalid
|
||||
*/
|
||||
protected validateTask(task: Task): void {
|
||||
if (!task.id) {
|
||||
throw new Error('Task ID is required');
|
||||
}
|
||||
if (!task.title) {
|
||||
throw new Error('Task title is required');
|
||||
}
|
||||
if (!task.description) {
|
||||
throw new Error('Task description is required');
|
||||
}
|
||||
if (!task.status) {
|
||||
throw new Error('Task status is required');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to sanitize tag names for file system safety
|
||||
* @param tag - Tag name to sanitize
|
||||
* @returns Sanitized tag name
|
||||
*/
|
||||
protected sanitizeTag(tag: string): string {
|
||||
return tag.replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user