diff --git a/ml-model/js/cli.js b/ml-model/js/cli.js index ae0fb47..e043deb 100755 --- a/ml-model/js/cli.js +++ b/ml-model/js/cli.js @@ -10,33 +10,45 @@ class OllamaAISelector { async getAvailableModels() { return new Promise((resolve, reject) => { - const ollama = spawn('ollama', ['list']); - let output = ''; - let error = ''; + try { + const ollama = spawn('ollama', ['list']); + let output = ''; + let error = ''; - ollama.stdout.on('data', (data) => { - output += data.toString(); - }); + ollama.stdout.on('data', (data) => { + output += data.toString(); + }); - ollama.stderr.on('data', (data) => { - error += data.toString(); - }); + ollama.stderr.on('data', (data) => { + error += data.toString(); + }); - ollama.on('close', (code) => { - if (code !== 0) { - reject(new Error(`Ollama list failed: ${error}`)); - return; - } + ollama.on('close', (code) => { + if (code !== 0) { + reject(new Error(`Ollama list failed: ${error}`)); + return; + } - // Parse ollama list output - const lines = output.trim().split('\n').slice(1); // Skip header - const models = lines - .filter(line => line.trim()) - .map(line => line.split(/\s+/)[0]) - .filter(model => model && !model.includes('NAME')); + // Parse ollama list output + const lines = output.trim().split('\n').slice(1); // Skip header + const models = lines + .filter(line => line.trim()) + .map(line => line.split(/\s+/)[0]) + .filter(model => model && !model.includes('NAME')); - resolve(models); - }); + resolve(models); + }); + + ollama.on('error', (err) => { + if (err.code === 'ENOENT') { + reject(new Error('Ollama not found. Please install Ollama from https://ollama.ai')); + } else { + reject(new Error(`Ollama spawn error: ${err.message}`)); + } + }); + } catch (spawnError) { + reject(new Error(`Failed to start Ollama: ${spawnError.message}`)); + } }); } @@ -44,14 +56,15 @@ class OllamaAISelector { console.log(`🚀 Running Ollama with ${modelName}...`); return new Promise((resolve, reject) => { - const args = ['run', modelName]; - if (prompt) { - args.push(prompt); - } + try { + const args = ['run', modelName]; + if (prompt) { + args.push(prompt); + } - const ollama = spawn('ollama', args, { - stdio: 'inherit' // Stream output directly to terminal - }); + const ollama = spawn('ollama', args, { + stdio: 'inherit' // Stream output directly to terminal + }); ollama.on('close', (code) => { if (code === 0) { @@ -61,9 +74,16 @@ class OllamaAISelector { } }); - ollama.on('error', (error) => { - reject(new Error(`Failed to start Ollama: ${error.message}`)); - }); + ollama.on('error', (error) => { + if (error.code === 'ENOENT') { + reject(new Error('Ollama not found. Please install Ollama from https://ollama.ai')); + } else { + reject(new Error(`Failed to start Ollama: ${error.message}`)); + } + }); + } catch (spawnError) { + reject(new Error(`Failed to start Ollama: ${spawnError.message}`)); + } }); } diff --git a/package.json b/package.json index 4025617..7af982a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "llm-checker", - "version": "2.3.2", + "version": "2.3.3", "description": "Intelligent CLI tool with AI-powered model selection that analyzes your hardware and recommends optimal LLM models for your system", "bin": { "llm-checker": "bin/enhanced_cli.js" diff --git a/src/models/deterministic-selector.js b/src/models/deterministic-selector.js index 3f0108c..4ef9ebe 100644 --- a/src/models/deterministic-selector.js +++ b/src/models/deterministic-selector.js @@ -221,7 +221,8 @@ class DeterministicModelSelector { } async getModelDetails(modelName) { - const details = await this.runOllamaCommand(['show', modelName]); + try { + const details = await this.runOllamaCommand(['show', modelName]); // Parse model details from ollama show output const meta = { @@ -236,7 +237,22 @@ class DeterministicModelSelector { model_identifier: modelName }; - return meta; + return meta; + } catch (error) { + // If Ollama is not available or model details can't be fetched, return minimal info + return { + name: modelName, + family: 'unknown', + paramsB: 0, + ctxMax: 2048, + quant: 'unknown', + sizeGB: 0, + modalities: ['text'], + tags: [], + model_identifier: modelName, + error: error.message + }; + } } /** @@ -404,20 +420,34 @@ class DeterministicModelSelector { async runOllamaCommand(args) { return new Promise((resolve, reject) => { - const proc = spawn('ollama', args, { stdio: 'pipe' }); - let output = ''; - let error = ''; - - proc.stdout.on('data', (data) => output += data); - proc.stderr.on('data', (data) => error += data); - - proc.on('close', (code) => { - if (code === 0) { - resolve(output); - } else { - reject(new Error(`Ollama command failed: ${error}`)); - } - }); + try { + const proc = spawn('ollama', args, { stdio: 'pipe' }); + let output = ''; + let error = ''; + + proc.stdout.on('data', (data) => output += data); + proc.stderr.on('data', (data) => error += data); + + proc.on('close', (code) => { + if (code === 0) { + resolve(output); + } else { + reject(new Error(`Ollama command failed: ${error}`)); + } + }); + + proc.on('error', (err) => { + // Handle ENOENT and other spawn errors gracefully + if (err.code === 'ENOENT') { + reject(new Error('Ollama not found. Please install Ollama from https://ollama.ai')); + } else { + reject(new Error(`Ollama spawn error: ${err.message}`)); + } + }); + } catch (spawnError) { + // Handle synchronous spawn errors + reject(new Error(`Failed to start Ollama: ${spawnError.message}`)); + } }); }