mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 17:55:26 -04:00
Fix Windows Cookbook background tasks, exit statuses, and empty SSH logs wrapper (#1389)
This commit consolidates all Windows Cookbook background fixes into a single comprehensive commit based on the latest main branch. Key fixes included: 1. React looksSuccessful Mismatch: Append 'DOWNLOAD_OK' for pip install commands in routes/cookbook_routes.py. 2. Local Windows SSH Wrapper & Log Directory Mismatch: Bypassed ssh wrappers and dynamically selected odysseus-tmux logs for local tasks in static/js/cookbookRunning.js. 3. WSL Bash Filtration: Filtered out the WSL bash stub at C:\Windows\System32\bash.exe in core/platform_compat.py. 4. Drive-Colon Path Normalization: Replaced .as_posix() with git_bash_path() in routes/shell_routes.py and src/bg_jobs.py. 5. GGUF-Only Hardware Fitting: Restructured local Windows recommendations to rank GGUF only in services/hwfit/fit.py. 6. Safe Win32 Process Liveness Probe: Replaced os.kill(pid, 0) with a safe Win32 API probe using GetExitCodeProcess in core/platform_compat.py. 7. Prebuilt llama-cpp-python Wheels: Supply the CPU extra index during compilation failure fallback. 8. Enforce UTF-8 log encoding: Set PYTHONIOENCODING=utf-8 on Windows bootstrap runners. 9. Fix Linux Llama.cpp Build script syntax error in routes/cookbook_helpers.py. 10. Page Reload Status Check: Run sys.executable instead of 'python3' to bypass Microsoft Store execution stubs on local Windows hosts. 11. Llama.cpp serve build bypass: Bypassed cmake compilation checks on local Windows and verified python bindings directly. 12. Serve Command Path Validation: Masked safe GGUF path printf subshells '' inside the serve command validator. 13. CPU Mismatch Diagnostics: Intercepted AVX2-lacking '0xc000001d' (Illegal Instruction) crashes in static/js/cookbook-diagnosis.js and guided users to Ollama. 14. Windows Pytest stability: Fixed stub import leakage in test files.
This commit is contained in:
@@ -426,6 +426,15 @@ export const ERROR_PATTERNS = [
|
||||
{ label: 'Copy install command', action: () => _copyText('pip install "llama-cpp-python[server]"') },
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /Windows Error 0xc000001d|Illegal instruction|0xc000001d/i,
|
||||
message: 'AVX2 Instruction Set Mismatch: the precompiled llama-cpp-python wheel requires CPU features (AVX2/FMA) that your processor or virtual machine lacks.',
|
||||
suggestion: 'Suggested action: switch this serve config to Ollama (highly recommended, has dynamic CPU fallbacks), or choose a remote Linux GPU server.',
|
||||
fixes: [
|
||||
{ label: 'Switch to Ollama', action: (panel) => _openServeEditFromDiagnosis(panel, { backend: 'ollama' }) },
|
||||
{ label: 'Choose remote server', action: (panel) => _openServeEditFromDiagnosis(panel) },
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /CUDA Toolkit not found|Unable to find cudart library|missing:\s*CUDA_CUDART/i,
|
||||
message: 'llama.cpp found nvcc, but the CUDA runtime library is missing.',
|
||||
|
||||
+12
-3
@@ -161,8 +161,17 @@ function _getPort(hostOrTask) {
|
||||
|
||||
/** Get platform for a given host (or task object). Returns 'windows', 'termux', 'linux', or '' */
|
||||
export function _getPlatform(hostOrTask) {
|
||||
if (!hostOrTask) return _envState.platform || '';
|
||||
if (typeof hostOrTask === 'object') return hostOrTask.platform || _getPlatform(hostOrTask.remoteHost);
|
||||
const isWinBrowser = (window.navigator.userAgent || window.navigator.platform || '').toLowerCase().includes('win');
|
||||
if (!hostOrTask || hostOrTask === 'local') {
|
||||
return _envState.platform || (isWinBrowser ? 'windows' : '');
|
||||
}
|
||||
if (typeof hostOrTask === 'object') {
|
||||
const h = hostOrTask.remoteHost;
|
||||
if (!h || h === 'local') {
|
||||
return hostOrTask.platform || _envState.platform || (isWinBrowser ? 'windows' : '');
|
||||
}
|
||||
return hostOrTask.platform || _getPlatform(h);
|
||||
}
|
||||
const srv = _envState.servers.find(s => s.host === hostOrTask);
|
||||
return srv?.platform || '';
|
||||
}
|
||||
@@ -637,7 +646,7 @@ async function _fetchDependencies() {
|
||||
const data = await resp.json();
|
||||
const pkgs = data.packages || [];
|
||||
if (!pkgs.length) { list.innerHTML = '<div class="hwfit-loading">No packages found</div>'; return; }
|
||||
const _winUnsupported = new Set(['diffusers', 'hf_transfer', 'vllm', 'rembg', 'gfpgan']);
|
||||
const _winUnsupported = new Set(['vllm', 'rembg', 'gfpgan']);
|
||||
|
||||
const _statusTag = (pkg, isLocal, isSystemDep, winBlocked) => {
|
||||
if (winBlocked) return `<span class="cookbook-dep-tag cookbook-dep-na">N/A</span>`;
|
||||
|
||||
@@ -2738,6 +2738,7 @@ async function _reconnectTask(el, task) {
|
||||
_updateTask(task.sessionId, { status: 'done', _doneConfirmAt: null, _lastStatusFlipAt: Date.now() });
|
||||
const _el = document.querySelector(`.cookbook-task[data-task-id="${task.sessionId}"]`);
|
||||
if (_el) {
|
||||
_clearDiagnosis(_el);
|
||||
_el.dataset.status = 'done';
|
||||
const _badge = _el.querySelector('.cookbook-task-status');
|
||||
if (_badge) { _badge.textContent = _statusLabel('done', task.type); _badge.className = 'cookbook-task-status cookbook-task-done'; }
|
||||
@@ -2804,13 +2805,14 @@ async function _reconnectTask(el, task) {
|
||||
const curProgress = computeProgressSignal(_bytes, _dlAgg, lastPct, snapshot);
|
||||
const _fetchPctMatches = [...snapshot.matchAll(/Fetching\s+\d+\s+files:\s*(\d+)%/g)];
|
||||
const _fetchPct = _fetchPctMatches.length ? parseInt(_fetchPctMatches[_fetchPctMatches.length - 1][1]) : null;
|
||||
const isPipDep = !!(task.payload && task.payload._dep);
|
||||
const _startupStalled = !_bytes && ((_dlAgg === 0) || (_fetchPct === 0)) && curProgress === '0';
|
||||
const _STALE_TIMEOUT = _startupStalled ? STARTUP_STALE_PROGRESS_MS : STALE_PROGRESS_MS;
|
||||
if (!el._lastProgress) { el._lastProgress = curProgress; el._lastProgressTime = Date.now(); }
|
||||
if (curProgress !== el._lastProgress) {
|
||||
el._lastProgress = curProgress;
|
||||
el._lastProgressTime = Date.now();
|
||||
} else if (Date.now() - (el._lastProgressTime || 0) > _STALE_TIMEOUT && task._autoRestarted) {
|
||||
} else if (!isPipDep && Date.now() - (el._lastProgressTime || 0) > _STALE_TIMEOUT && task._autoRestarted) {
|
||||
const mins = Math.floor((Date.now() - (el._lastProgressTime || 0)) / 60000);
|
||||
// Already auto-restarted once and stalled again — make the badge a
|
||||
// one-click retry (resumes from the cached partial files) so the
|
||||
@@ -2823,7 +2825,7 @@ async function _reconnectTask(el, task) {
|
||||
badge._retryBound = true;
|
||||
badge.addEventListener('click', (e) => { e.stopPropagation(); _retryTask(el, task); });
|
||||
}
|
||||
} else if (Date.now() - (el._lastProgressTime || 0) > _STALE_TIMEOUT && !task._autoRestarted) {
|
||||
} else if (!isPipDep && Date.now() - (el._lastProgressTime || 0) > _STALE_TIMEOUT && !task._autoRestarted) {
|
||||
task._autoRestarted = true;
|
||||
_updateTask(task.sessionId, { _autoRestarted: true });
|
||||
badge.textContent = _startupStalled ? '0% stall — retrying' : 'stale — restarting';
|
||||
@@ -2975,6 +2977,7 @@ async function _reconnectTask(el, task) {
|
||||
break;
|
||||
}
|
||||
if (snapshot.includes('DOWNLOAD_OK') || (snapshot.includes('/snapshots/') && completed >= totalFiles && totalFiles > 0)) {
|
||||
_clearDiagnosis(el);
|
||||
_dlRetryCount.delete(task.payload?.repo_id || task.name);
|
||||
badge.textContent = _statusLabel('done', task.type);
|
||||
badge.className = 'cookbook-task-status cookbook-task-done';
|
||||
|
||||
Reference in New Issue
Block a user