fix(cookbook): stop-all no longer auto-retries interrupted HF downloads fixes (#1474)
* fix(cookbook): stop-all no longer auto-retries interrupted HF downloads When C-c was sent to a running download, the bash wrapper printed DOWNLOAD_FAILED on non-zero exit (SIGINT = 130). The reconnect polling loop was still running at that point, saw the failure marker, and silently relaunched the download — making "Stop all" appear to have no effect while the UI showed the toast as if it succeeded. Fix: abort the reconnect controller immediately when the stop button is clicked (before the kill command is dispatched), and guard the auto-retry condition with !controller.signal.aborted so that any in-flight poll that completes after abort cannot trigger a retry. Fixes #1458 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix Edge/Chromium sidebar section-title clipping (#1420) Sidebar section titles were vertically clipped in Chromium/Edge (fine in Firefox). Raise line-height 1 → 1.3, mirroring the existing .list-item fix. The titles are flex-centred in a fixed-height (29px) header, so this adds glyph headroom without any reflow. * Drop GPU-only flags from the CPU-only (-ngl 0) serve command (#1433) A CPU-only llama.cpp serve config still emitted --flash-attn on and exported GGML_CUDA_ENABLE_UNIFIED_MEMORY=1 (independent toggles, often left on by an Auto profile), so the command mixed "zero GPU layers" with CUDA/flash-attn and failed to start (issue #1291). Gate both on a _cpuOnly check (ngl == 0). GPU serving is unchanged — the gate only affects the ngl=0 path. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: APIKeyManager.load crashes app startup on a corrupt/wrong-shape api_keys.json (#1565) * Don't lose deep-research findings when synthesis times out (#1551) (#1562) Two problems made deep research report "No information could be gathered" even after it had extracted findings, on slow local models (reporter served a 20B via LM Studio): - _synthesize hard-capped its LLM call at timeout=60, while extraction uses the user's extraction_timeout (300s here) and the final report uses 180s. The slow model needed >60s to synthesize the round's findings, so synthesis timed out after 3 attempts. Raised it to 180s to match the final-report call. - When synthesis produced no report (it returns the unchanged, still-empty report on failure during round 1), the run hit `if not report: return "No information could be gathered…"` and discarded the findings it had already gathered. Now it falls back to a compiled report built from those findings (_fallback_report) so the user keeps the gathered material. Tests stub the LLM (no live model/DB), pin the synthesis timeout >= 180, that the fallback surfaces the findings rather than the give-up message, and that a failed synthesis preserves the previous report. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: return sorted model list on first call in group chat (#1484) Both _getModels() and getAllModels() store the sorted copy in a cache variable but return the original unsorted array on first invocation. Subsequent calls return the cache (sorted), causing inconsistent model picker ordering on first render. * fix: guard sp.destroy() in _loadScheduled against null spinner (#1495) When the scheduled folder is opened with cached data, sp is null (the loading spinner is skipped). _loadScheduled receives null and calls sp.destroy() unconditionally, crashing with TypeError. * fix: capture download exit code before test consumes it (#1497) The shell pattern 'if [ $? -eq 0 ]; ... else ... echo DOWNLOAD_FAILED (exit $?)' always reports 'exit 1' because $? inside the else branch is the exit code of the [ test command, not the download. Capture into _ec first. * fix: guard uid.decode() in auto-classify warning log against str UIDs (#1472) Every other uid.decode() call in this function uses 'uid.decode() if isinstance(uid, bytes) else str(uid)' but the warning at line 832 does bare uid.decode(), crashing with AttributeError when uid is already a string. * fix: guard AI tidy verdict against non-string LLM output (#1486) The AI document-tidy endpoint parses verdicts from LLM JSON output and calls .lower().strip() directly. If the model returns null or a non-string element, this crashes with AttributeError. Coerce to str so malformed output is treated as 'keep' instead of crashing. * fix: rename local url-quote import to avoid shadowing module-level _q (#1471) The 'from urllib.parse import quote as _q' at line 734 shadows the module-level _q (istrstrstrstrstrstrIMAPutility) imported from email_helpers, causing UnboundLocalError at lines 191 and 278 where _q is used before the local import executes. This silently breaks the entire auto-summarize pass. * fix(ui): add missing Escape key handlers for email-lib-modal, model-picker-menu, and sort dropdowns (#1487) CONTEXT: Several interactive elements lacked Escape key handlers: the email library modal was not in dynamicModals, the model-picker popup had no Escape close, and the session/model sort dropdowns only closed on outside click. CHANGE: Adds email-lib-modal to the dynamicModals array in the Escape handler so it gets dismissed via dismissModal. Adds a check for model-picker-menu.open before the modal chain to close the dropdown on Escape. Adds checks for session-sort-dropdown and model-sort-dropdown display=block before the document panel minimize fallback. WHY: Users expect consistent Escape-to-close behavior across all modals, overlays, and popups. These four were the only interactive containers in the app that ignored the Escape key entirely. IMPACT: Pressing Escape now closes the email library modal, model picker popup, session sort dropdown, and model sort dropdown -- matching user expectations and the behavior of every other modal in the app. * fix: mcp CLI _serialize crashes when stored env JSON is a list (#1609) * fix: validate_caldav_url crashes with TypeError on a non-string URL (#1608) * fix: _sanitize_export_filename crashes on a non-string session name (#1607) * fix: shared MCP truncate() crashes on None/non-string tool output (#1605) * fix: search query helpers crash on a non-string query (#1604) * fix: rag_server add/remove_directory crashes on a non-string directory arg (#1614) * fix: gallery CLI image serialization crashes on a non-string prompt (#1598) * fix: research CLI summary crashes on a non-string query (#1596) * fix: skills CLI summary crashes on a non-string description (#1595) * fix(cookbook): set UTF-8 encoding for detached download/serve subprocesses (#1599) On Windows, Python defaults to the active code page (cp1252) for subprocess I/O. HuggingFace CLI outputs U+2713 (✓) when validating tokens, which cp1252 cannot encode, crashing the download process. Set PYTHONUTF8=1 and PYTHONIOENCODING=utf-8 in the subprocess environment so Unicode output from hf/pip/llama-server is handled correctly. Fixes #1543 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: clarify host Ollama with Docker (#1594) * fix(ui): stop welcome-screen tip from clipping on narrow phones (#1612) The empty-state tip ("Add an AI endpoint from Settings...") shares a 60px max-height ceiling with the one-line .welcome-sub / .welcome-version. On narrow phones the welcome block shrink-wraps and the tip wraps to 4-5 lines (~67px), so the shared ceiling clipped its last line ("...key into the chat.") - the only setup hint a first-run user gets. Give .welcome-tip its own taller max-height (120px), placed above the @media (max-height: 650px) block so that rule's max-height:0 still collapses the tip on short viewports. .welcome-sub / .welcome-version are untouched, and desktop is unchanged (the tip is ~50px there, well under the ceiling). * Save only string personal doc paths (#1566) * Reject backup output inside data dir (#1587) * Parse all AMD GPU check args (#1586) * Require runnable dispatcher subcommands (#1585) * Require runnable dispatcher subcommands * Use modern dispatcher test loader * Remove duplicate update database body (#1584) * Skip invalid research service sources (#1583) * Reject CalDAV writeback events without uid (#1582) * Reject empty mail CLI recipients (#1581) * Reject empty mail CLI recipients * Keep mail CLI test imports isolated * Validate signature CLI PNG data (#1580) * Validate signature CLI PNG data * Keep signature CLI test imports isolated * Reject invalid preset CLI entries (#1579) * Reject invalid preset CLI entries * Use modern preset CLI test loader * Normalize session CLI counters (#1578) * Normalize session CLI counters * Keep sessions CLI test imports isolated * fix: monthly schedule label shows 21th/22th/31th (ordinal suffix for days >20) (#1577) * fix: split_chunks emits a duplicate trailing chunk for text over size-overlap (#1573) * fix: builtin_actions heuristics crash on a truthy non-string input (#1639) * fix: skill test-task / precision helpers crash on a non-dict skill (#1638) * fix: logs CLI _resolve crashes on a non-string name (#1631) * fix: _extract_skill_json crashes on a truthy non-string teacher response (#1630) * fix: tool-block parsing crashes on a non-string input (#1628) * fix: check_outbound_url crashes on a truthy non-string URL (#1623) * fix: document_actions title/content helpers crash on non-string input (#1621) * fix: inside_base_dir raises TypeError on a non-string path instead of failing closed (#1619) * fix: is_markitdown_format crashes on a non-string path (#1618) * Close app_api blocklist gap for bare /api/tokens and /api/users The blocklist prefixes had trailing slashes, so path.startswith() only matched /api/tokens/{id} but not /api/tokens itself — the bare GET (list) and POST (mint) endpoints were reachable via app_api. Same gap on /api/users (list/create/delete). Drop trailing slashes so both bare and sub-resource forms are blocked. /api/auth and /api/admin had no bare endpoints today but get the same treatment to prevent future drift. Caught by #1462. * Decrypt CalDAV password before write-back (#1731) writeback_event read cfg["password"] (the encrypted blob) and passed it straight to DAVClient, so every local create/edit/delete authenticated with the literal ciphertext, the remote rejected it, and the change never reached the server — the exact silent-write-loss this module was built to prevent. The pull path src/caldav_sync.py already decrypts; mirror that. decrypt() is a no-op on legacy plaintext. Caught by #1731. * Memory MCP delete: match exact id, not prefix (#1303) The delete action looked up the target with startswith() to capture full_id, but then re-applied startswith() to filter the list — so a short or ambiguous memory_id silently deleted every memory whose id shared the prefix, while the success message reported only the first match. The edit action used the first match and stopped, so the two actions disagreed on multi-match behaviour. Use full_id for both. Caught by #1303. * Rebuild memory vector index from the full saved set, not just the audited owner (#1747) audit_memories saves final_entries merged with other owners' entries (correct), but then rebuilt the shared vector collection from final_entries alone — wiping every other owner from semantic search until they happened to run their own audit. Keyword fallback masked it, so it degraded silently. Capture saved_entries once and rebuild from that. Caught by #1747. * Owner-scope RAG doc ids so identical chunks across users don't collide (#1738, #1760) _generate_doc_id hashed only text. add_document / add_documents_batch early-return when the id exists, so the second owner indexing a byte-identical chunk hit the first owner's id, was silently dropped, and never stored under their owner — their owner-filtered search then quietly omitted it. Hash owner + text; empty owner reproduces the legacy id, so the unowned/base index keeps existing ids and isn't re-churned. Same-owner identical chunks still dedupe. Caught by #1738 and #1760 (independent reports of the same bug). * Removed duplicate definition of _preview_text() --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Zeus-Deus <100132710+Zeus-Deus@users.noreply.github.com> Co-authored-by: lekt8 <lewistham9x@gmail.com> Co-authored-by: Afonso Coutinho <afonso@omelhorsite.pt> Co-authored-by: Paulo Victor Cordeiro <146781332+pvcordeiro@users.noreply.github.com> Co-authored-by: Zarl-prog <asimjunaidi5u@gmail.com> Co-authored-by: Wes Huber <wesleybaxterhuber@gmail.com> Co-authored-by: .bulat <its.bulat@icloud.com> Co-authored-by: Mahdi Salmanzade <mahdisalmanzadehasl@gmail.com> Co-authored-by: red person <redpersoncoding@gmail.com> Co-authored-by: pewdiepie-archdaemon <pewdiepie-archdaemon@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
dc365a1b27
commit
88754035ce
@@ -2266,6 +2266,10 @@ export function _renderRunningTab() {
|
||||
|
||||
// Wire stop
|
||||
el.querySelector('.cookbook-task-action-stop').addEventListener('click', async () => {
|
||||
// Abort the reconnect loop before sending kill so that a DOWNLOAD_FAILED
|
||||
// marker written by the shell wrapper (on SIGINT/non-zero exit) cannot
|
||||
// trigger an auto-retry after a manual stop.
|
||||
if (el._abort) el._abort.abort();
|
||||
const badge = el.querySelector('.cookbook-task-status');
|
||||
if (badge) { badge.textContent = 'stopping...'; badge.className = 'cookbook-task-status cookbook-task-stopping'; }
|
||||
el.dataset.status = 'stopped';
|
||||
@@ -2762,7 +2766,7 @@ async function _reconnectTask(el, task) {
|
||||
const _accessDenied = /Access to model.*is restricted|gated repo|GatedRepoError|401 Unauthorized|403 Forbidden|not in the authorized list|awaiting a review|must (?:be authenticated|have access)/i.test(snapshot);
|
||||
const _dlKey = task.payload?.repo_id || task.name;
|
||||
const _dlN = _dlRetryCount.get(_dlKey) || 0;
|
||||
if (!_accessDenied && !task._userStopped && task.type === 'download' && task.payload && _dlN < _DL_MAX_AUTO_RETRY) {
|
||||
if (!controller.signal.aborted && !_accessDenied && task.type === 'download' && task.payload && _dlN < _DL_MAX_AUTO_RETRY) {
|
||||
// Auto-retry: kill the dead session and re-launch (resumes from
|
||||
// the cached .incomplete files) after a short delay.
|
||||
_dlRetryCount.set(_dlKey, _dlN + 1);
|
||||
|
||||
Reference in New Issue
Block a user