diff --git a/static/js/cookbook-hwfit.js b/static/js/cookbook-hwfit.js index 6817d15..818ca7d 100644 --- a/static/js/cookbook-hwfit.js +++ b/static/js/cookbook-hwfit.js @@ -887,7 +887,30 @@ export function _expandModelRow(row, modelData) { const quickRunBtn = panel.querySelector('.hwfit-quickrun-btn'); if (quickRunBtn) { quickRunBtn.addEventListener('click', async () => { - _syncHostFromScanDropdown(); + const _qrHost = _syncHostFromScanDropdown(); + + // Don't serve a model that isn't downloaded yet. vLLM/SGLang would + // background-pull at launch, so the serve task shows up as "running" in + // the Running tab while nothing is actually served (and llama.cpp just + // errors "No GGUF found"). The Configure button and the Serve tab already + // gate on the cached-model list — mirror that here. When the model isn't + // present, honor the button's "Download" half by kicking off the download + // instead, then the user can Run again to serve once it finishes. + const _short = modelData.name.split('/').pop(); + const _downloaded = _cachedModelIds && ( + _cachedModelIds.has(modelData.name) + || [..._cachedModelIds].some(id => id === modelData.name || id.endsWith('/' + _short)) + ); + if (_cachedModelIds && !_downloaded) { + uiModule.showToast('Model not downloaded yet — starting download. Run again to serve once it finishes.'); + if (backend === 'ollama') { + _runPanelCmd(panel, _buildDownloadCmd(modelData, backend), { timeout: 0 }); + } else { + _runModelDownload(panel, modelData, backend, _qrHost); + } + return; + } + quickRunBtn.disabled = true; quickRunBtn.textContent = 'Starting...';