Closes#1695.
@Patrick-81 reported the bare "AIAgent not available -- check that
hermes-agent is on sys.path" error on a symlinked install (~/Programmes/hermes-agent
linked to ~/hermes-agent). The maintainer's response — three diagnostic
commands plus `pip install -e .` in the agent dir — fixed it for them.
This PR captures both halves of that learning so the next user with the
same shape doesn't have to file a new issue:
1. **Error message diagnostic block.** New helper
`_aiagent_import_error_detail()` in api/streaming.py builds a multi-line
diagnostic when the import fails, including:
- the running Python interpreter
- HERMES_WEBUI_AGENT_DIR (set value, or "(not set)")
- sys.path entries that mention hermes/agent (or "no entries mention..."
— itself a strong diagnostic signal)
- the most-common fix (`pip install -e .` in the agent dir)
- a pointer to docs/troubleshooting.md
The original error message string is preserved as the FIRST line so
existing log scrapers and docs-search keep matching.
Helper is kept as a separate function so it stays out of the hot path
until we actually need to raise — building it on every successful import
would be wasted work.
2. **New docs/troubleshooting.md.** Symptom → Why → Diagnostic commands →
Fix → When-to-file-a-bug template, with one entry to start: the
"AIAgent not available" flow Patrick-81 walked through. Future
recurring failure modes follow the same template. Required a one-line
addition to .gitignore — docs/* is gitignored with an allowlist, and
the new file needed `!docs/troubleshooting.md` to be tracked.
3. **README link.** docs/troubleshooting.md added to the `## Docs` section
so users know where to look first.
13 regression tests in tests/test_1695_aiagent_import_error_detail.py:
9 for the helper output shape (preserves original message line, includes
running python, shows HERMES_WEBUI_AGENT_DIR set/unset both ways, includes
pip-install-e hint, points at troubleshooting doc, lists relevant sys.path
entries when present, says "no entries..." when absent, output is multi-line)
plus 4 for the docs-presence regression (file exists, has the AIAgent
section, includes pip install -e ., describes the diagnostic chain with
readlink + agent/__init__.py verification).
190 streaming/aiagent tests pass after the change. ast.parse on
api/streaming.py clean.
CI failure on prior push was due to the docs/* gitignore swallowing the
new troubleshooting.md file silently — this commit adds the allowlist
entry so the file is tracked.
Hide preserved compression task lists when the latest todo tool state
shows no pending or in-progress items. This prevents completed tasks from
reappearing after reloads or context compaction.
Tests: uv run --with pytest --with pyyaml python -m pytest -q tests/test_auto_compression_card.py
Tests: node --check static/ui.js
On some setups the localStorage quota is exhausted; the bare setItem
call throws an unhandled DOMException that breaks model selection and
prevents the chat UI from loading.
Wrap both call-sites (boot.js model-select onChange, onboarding.js
_saveOnboardingDefaults) in try/catch so the error is logged to the
console as a warning instead of surfacing as a fatal exception.
Fixes: 'Failed to execute setItem on Storage: Setting the value of
hermes-webui-model exceeded the quota.'
The file-tree row tooltip says 'Double-click to rename' on every entry,
but folders don't actually rename on double-click — they navigate via
loadDir(). The tooltip is therefore misleading on directory rows.
Reported by @Deor in the WebUI Discord testers thread (May 5 2026):
'Ah that works yeah. May want to change the popup text as it also says
double click at the moment.'
Fix: gate the tooltip on item.type !== 'dir' so it only attaches to file
rows, where double-click does what the hint advertises. Folder rename
still reachable via the right-click context menu (unchanged).
Companion to #1698/#1702/#1707 — completes the rename-affordance triage:
- #1698 fixed: dblclick rename was unreachable on files (preview hijacked)
- #1707 fixed: single-click on filename did nothing (over-aggressive guard)
- #1710 (this PR): tooltip claimed dblclick-rename on folders too
Closes#1710
Tests: 4 source-level regression tests in tests/test_1710_folder_tooltip.py
guard the gate, the unchanged dir-dblclick navigate behaviour, the i18n key,
and that files still receive the tooltip. All 13 file-tree handler tests
(4 new + 9 from #1707) pass.
Closes#1707 — single-click on a workspace tree filename did nothing.
#1698 was a regression where the filename's dblclick rename handler was
unreachable because the row's el.onclick (openFile) fired synchronously
on the first click. The fix in #1702 stopped click propagation on nameEl
— but that broke single-click activation entirely (#1707): clicking the
filename now did nothing, you had to click the icon or row whitespace
to open the file.
Restored fix preserves both intents via a 300ms debounced delegator:
let _nameClickTimer = null;
nameEl.onclick = (e) => {
e.stopPropagation();
if (_nameClickTimer) { clearTimeout(_nameClickTimer); _nameClickTimer = null; }
_nameClickTimer = setTimeout(() => {
_nameClickTimer = null;
if (typeof el.onclick === 'function') el.onclick(e);
}, 300);
};
nameEl.ondblclick = (e) => {
e.stopPropagation();
if (_nameClickTimer) { clearTimeout(_nameClickTimer); _nameClickTimer = null; }
// ... existing rename body
};
Single-click on nameEl schedules a setTimeout that calls el.onclick(e)
after the dblclick threshold passes (300ms — matches the OS dblclick
threshold on most platforms). Double-click cancels the pending timer
and triggers the existing rename input.
Cost: 300ms latency on file-open clicks. Acceptable trade for keeping
rename reachable on single-click.
Also updated tests/test_workspace_tree_rename.py to accept both the
pre-#1707 (pure stopPropagation) and post-#1707 (debounced delegator)
shapes — the original assertion was too narrow and would have rejected
the correct fix.
9 new regression tests in tests/test_1707_workspace_filename_click.py:
- 6 source-level static-analysis checks on the patched handler shape
- 3 behavioral tests via Node VM (synthesize click → 300ms delay,
click → dblclick within tick → assert rename mounts + openFile
is not called).
7 of 9 tests fail on master pre-fix (verified); all 9 pass after.
- Add .model-opt-provider chip (right-aligned, muted) on every model row
that belongs to a provider group, making same-name models across
providers visually distinguishable at a glance.
- Add per-group model count to group headings: 'OpenRouter (47)'.
- Add subtle border-top divider between provider groups for visual
separation during scroll.
Scope: Shape A from #1425 — smallest change, ~15 LOC, no API churn.
Note: Settings model picker is a native <select> and already has optgroup
labels; this targets the custom dropdown used in the composer.
Closes#1425