UNPKG

@sirmrmarty/n8n-nodes-tmux-orchestrator

Version:

n8n nodes for orchestrating Claude AI agents through tmux sessions

171 lines (147 loc) 4.7 kB
/** * Dynamic Claude Model Manager * Provides up-to-date Claude model options with fallback to static list */ export interface ClaudeModel { name: string; value: string; description?: string; isRecommended?: boolean; } export interface ModelManagerConfig { includeDeprecated?: boolean; includeExperimental?: boolean; cacheDuration?: number; // in minutes } export class ModelManager { private static instance: ModelManager; private cachedModels: ClaudeModel[] | null = null; private lastFetch: Date | null = null; private readonly cacheDuration: number; // Claude Code available models - simplified list private readonly knownModels: ClaudeModel[] = [ { name: 'Sonnet (Latest)', value: 'sonnet', description: 'Latest Sonnet model', isRecommended: true, }, { name: 'Opus (Latest)', value: 'opus', description: 'Latest Opus model', isRecommended: true, }, ]; private readonly legacyModels: ClaudeModel[] = []; private constructor(config: ModelManagerConfig = {}) { this.cacheDuration = config.cacheDuration || 60; // 1 hour default } public static getInstance(config?: ModelManagerConfig): ModelManager { if (!ModelManager.instance) { ModelManager.instance = new ModelManager(config); } return ModelManager.instance; } /** * Get all available Claude models */ public async getAvailableModels(config: ModelManagerConfig = {}): Promise<ClaudeModel[]> { // Check cache first if (this.isCacheValid()) { return this.cachedModels!; } try { // Try to fetch latest models (placeholder for future API integration) const models = await this.fetchLatestModels(config); this.cachedModels = models; this.lastFetch = new Date(); return models; } catch (error) { console.warn('Failed to fetch latest models, using known models:', error.message); // Fallback to known models return this.getKnownModels(config); } } /** * Get models for n8n node options format */ public async getModelOptions(config: ModelManagerConfig = {}): Promise<Array<{ name: string; value: string }>> { const models = await this.getAvailableModels(config); return models.map(model => ({ name: model.name, value: model.value, })); } /** * Validate if a model is available */ public async isValidModel(modelValue: string): Promise<boolean> { const models = await this.getAvailableModels(); return models.some(model => model.value === modelValue); } /** * Get recommended model */ public async getRecommendedModel(): Promise<ClaudeModel> { const models = await this.getAvailableModels(); const recommended = models.find(model => model.isRecommended); return recommended || models[0]; // Fallback to first model } /** * Get model by value */ public async getModelByValue(value: string): Promise<ClaudeModel | null> { const models = await this.getAvailableModels(); return models.find(model => model.value === value) || null; } private isCacheValid(): boolean { if (!this.cachedModels || !this.lastFetch) { return false; } const now = new Date(); const diffInMinutes = (now.getTime() - this.lastFetch.getTime()) / (1000 * 60); return diffInMinutes < this.cacheDuration; } private async fetchLatestModels(config: ModelManagerConfig): Promise<ClaudeModel[]> { // Future implementation: Could fetch from Anthropic API or configuration service // For now, simulate API call and return known models await new Promise(resolve => setTimeout(resolve, 100)); // Simulate network call // This would be replaced with actual API call in the future return this.getKnownModels(config); } private getKnownModels(config: ModelManagerConfig = {}): ClaudeModel[] { let models = [...this.knownModels]; // Add legacy models if requested if (config.includeDeprecated !== false) { models = [...models, ...this.legacyModels]; } // Sort by recommendation and then by name models.sort((a, b) => { if (a.isRecommended && !b.isRecommended) return -1; if (!a.isRecommended && b.isRecommended) return 1; return a.name.localeCompare(b.name); }); return models; } /** * Clear cache and force refresh on next request */ public clearCache(): void { this.cachedModels = null; this.lastFetch = null; } /** * Get Claude Command Options string for the given model */ public getClaudeCommandOptions(model: string): string { // Map model values to Claude CLI options const modelMappings: Record<string, string> = { 'sonnet': '--model sonnet', 'opus': '--model opus', }; return modelMappings[model] || `--model ${model}`; } } // Export singleton instance export const modelManager = ModelManager.getInstance();