This commit is contained in:
Pavelevich 2025-09-08 23:26:37 +02:00
parent 02f69b79c9
commit 36b3200443
6 changed files with 91 additions and 32 deletions

View file

@ -207,6 +207,14 @@ Alternative options:
---
## 🔒 Security & Caching
- Installation guidance: For Ollama on Linux, prefer official package managers or documented methods rather than piping remote scripts into the shell. See the official installation docs: https://github.com/ollama/ollama/blob/main/docs/linux.md
- Cache location: The Ollama model cache used by LLM Checker is stored at `~/.llm-checker/cache/ollama`.
- Backward compatibility: Existing cache files in the legacy path (`src/ollama/.cache`) are still read if present, but new cache writes go to the home directory.
---
## 🚀 **What's New in v2.7.0**
### 🎯 **Complete Windows High-End GPU Optimization**
@ -269,4 +277,4 @@ If you find LLM Checker useful, please consider:
- Reporting issues 🐛
- Sharing with others 📢
**Buy me a coffee:** [github.com/signerless/llm-checker](https://github.com/signerless/llm-checker)
**Buy me a coffee:** [github.com/signerless/llm-checker](https://github.com/signerless/llm-checker)

View file

@ -11,9 +11,21 @@ const fs = require('fs');
const path = require('path');
// Function to search Ollama models by use case
function getOllamaCacheFile(filename) {
try {
const homePath = path.join(os.homedir(), '.llm-checker', 'cache', 'ollama', filename);
const legacyPath = path.join(__dirname, '../src/ollama/.cache', filename);
if (fs.existsSync(homePath)) return homePath;
if (fs.existsSync(legacyPath)) return legacyPath;
return homePath; // default preferred path
} catch {
return path.join(__dirname, '../src/ollama/.cache', filename);
}
}
function searchOllamaModelsForUseCase(useCase, hardware) {
try {
const cacheFile = path.join(__dirname, '../src/ollama/.cache/ollama-detailed-models.json');
const cacheFile = getOllamaCacheFile('ollama-detailed-models.json');
if (!fs.existsSync(cacheFile)) return [];
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
@ -209,7 +221,7 @@ function estimateModelSize(model) {
function getRealSizeFromOllamaCache(model) {
try {
const cacheFile = path.join(__dirname, '../src/ollama/.cache/ollama-detailed-models.json');
const cacheFile = getOllamaCacheFile('ollama-detailed-models.json');
if (!fs.existsSync(cacheFile)) return null;
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
@ -348,11 +360,12 @@ function getOllamaInstallInstructions() {
name: 'Linux',
downloadUrl: 'https://ollama.com/download/linux',
instructions: [
'1. Run the installation script:',
' curl -fsSL https://ollama.com/install.sh | sh',
'2. Start Ollama service:',
'1. Review official installation options:',
' https://github.com/ollama/ollama/blob/main/docs/linux.md',
'2. Prefer a package manager (apt/dnf/pacman) when available',
'3. Start service after install:',
' sudo systemctl start ollama',
'3. Test with: ollama run llama2:7b'
'4. Test with: ollama run llama2:7b'
],
alternativeInstall: 'Manual install: https://github.com/ollama/ollama/blob/main/docs/linux.md'
}
@ -2396,4 +2409,4 @@ program
console.log(chalk.gray('For silent mode: ') + chalk.cyan.bold('llm-checker check --no-verbose'));
});
program.parse();
program.parse();

View file

@ -30,7 +30,8 @@ async function diagnoseOllama() {
console.log(` Details: ${testResult.details}`);
console.log('\n🔧 Possible solutions:');
console.log('1. Install Ollama: curl -fsSL https://ollama.ai/install.sh | sh');
console.log('1. Install Ollama (review official docs and prefer package manager):');
console.log(' https://github.com/ollama/ollama#installation');
console.log('2. Start Ollama: ollama serve');
console.log('3. Check if running: curl http://localhost:11434/api/version');
}

View file

@ -1,6 +1,6 @@
{
"name": "llm-checker",
"version": "2.7.1",
"version": "2.7.2",
"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"

View file

@ -179,22 +179,27 @@ test_installation() {
# Install Ollama (optional)
install_ollama() {
print_status "Would you like to install Ollama? (y/N)"
print_status "Would you like guidance to install Ollama? (y/N)"
read -r response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
print_status "Installing Ollama..."
if [[ "$OSTYPE" == "linux-gnu"* ]] || [[ "$OSTYPE" == "darwin"* ]]; then
curl -fsSL https://ollama.ai/install.sh | sh
print_success "Ollama installed successfully"
print_status "You can now use: ollama pull llama3.2:3b"
if [[ "$OSTYPE" == "darwin"* ]]; then
print_status "On macOS you can use Homebrew (recommended):"
echo " brew install ollama"
print_status "Or download from: https://ollama.com/download/mac"
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
print_status "On Linux, please follow official installation options:"
echo " https://github.com/ollama/ollama/blob/main/docs/linux.md"
print_warning "Avoid piping remote scripts directly to shell unless you have reviewed them."
else
print_status "Please visit https://ollama.ai to install Ollama on Windows"
print_status "Please visit https://ollama.ai to install Ollama for your platform"
fi
print_status "After installation, start the service if needed and test:"
echo " ollama serve"
echo " ollama run llama2:7b"
else
print_status "Skipping Ollama installation"
print_status "You can install it later from: https://ollama.ai"
print_status "Skipping Ollama installation guidance"
print_status "You can review options later at: https://ollama.ai"
fi
}
@ -238,4 +243,4 @@ main() {
}
# Run main function
main "$@"
main "$@"

View file

@ -1,15 +1,24 @@
const https = require('https');
const fs = require('fs');
const path = require('path');
const os = require('os');
const { classifyAllModels } = require('../utils/model-classifier');
class OllamaNativeScraper {
constructor() {
this.baseURL = 'https://ollama.com';
this.registryAPI = 'https://registry.ollama.ai';
this.cacheDir = path.join(__dirname, '.cache');
// New secure cache location (user home)
this.cacheDir = path.join(os.homedir(), '.llm-checker', 'cache', 'ollama');
this.cacheFile = path.join(this.cacheDir, 'ollama-models.json');
this.detailedCacheFile = path.join(this.cacheDir, 'ollama-detailed-models.json');
// Legacy cache location (inside repo) for backward compatibility
this.legacyCacheDir = path.join(__dirname, '.cache');
this.legacyCacheFile = path.join(this.legacyCacheDir, 'ollama-models.json');
this.legacyDetailedCacheFile = path.join(this.legacyCacheDir, 'ollama-detailed-models.json');
this.cacheExpiry = 6 * 60 * 60 * 1000; // 6 horas para actualizar más frecuentemente
if (!fs.existsSync(this.cacheDir)) {
@ -29,17 +38,29 @@ class OllamaNativeScraper {
'User-Agent': 'Mozilla/5.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
// Do not claim compression we don't handle here
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
...options.headers
},
...options
}
};
const timeoutMs = typeof options.timeout === 'number' ? options.timeout : 15000;
const maxBytes = typeof options.maxBytes === 'number' ? options.maxBytes : 5 * 1024 * 1024; // 5MB
const req = https.request(requestOptions, (res) => {
let data = '';
res.on('data', chunk => { data += chunk; });
let received = 0;
res.on('data', chunk => {
received += chunk.length;
if (received > maxBytes) {
req.destroy(new Error('Response too large'));
return;
}
data += chunk.toString('utf8');
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve({ statusCode: res.statusCode, data, headers: res.headers });
@ -49,6 +70,11 @@ class OllamaNativeScraper {
});
});
// Socket/request timeout
req.setTimeout(timeoutMs, () => {
req.destroy(new Error('Request timeout'));
});
req.on('error', reject);
if (options.body) req.write(options.body);
req.end();
@ -142,15 +168,18 @@ class OllamaNativeScraper {
}
isCacheValid() {
if (!fs.existsSync(this.cacheFile)) return false;
const stats = fs.statSync(this.cacheFile);
const file = fs.existsSync(this.cacheFile) ? this.cacheFile : (fs.existsSync(this.legacyCacheFile) ? this.legacyCacheFile : null);
if (!file) return false;
const stats = fs.statSync(file);
const age = Date.now() - stats.mtime.getTime();
return age < this.cacheExpiry;
}
readCache() {
try {
const data = fs.readFileSync(this.cacheFile, 'utf8');
const file = fs.existsSync(this.cacheFile) ? this.cacheFile : this.legacyCacheFile;
if (!file) return null;
const data = fs.readFileSync(file, 'utf8');
return JSON.parse(data);
} catch {
return null;
@ -173,15 +202,18 @@ class OllamaNativeScraper {
}
isDetailedCacheValid() {
if (!fs.existsSync(this.detailedCacheFile)) return false;
const stats = fs.statSync(this.detailedCacheFile);
const file = fs.existsSync(this.detailedCacheFile) ? this.detailedCacheFile : (fs.existsSync(this.legacyDetailedCacheFile) ? this.legacyDetailedCacheFile : null);
if (!file) return false;
const stats = fs.statSync(file);
const age = Date.now() - stats.mtime.getTime();
return age < this.cacheExpiry;
}
readDetailedCache() {
try {
const data = fs.readFileSync(this.detailedCacheFile, 'utf8');
const file = fs.existsSync(this.detailedCacheFile) ? this.detailedCacheFile : this.legacyDetailedCacheFile;
if (!file) return null;
const data = fs.readFileSync(file, 'utf8');
return JSON.parse(data);
} catch {
return null;