Commit Graph

51004 Commits

Author SHA1 Message Date
flyer
766ab6dd2d fix(desktop): render Mermaid labels that contain <br/>
`mermaid.render()` returns SVG aimed at inline HTML, and its sanitizer
gives back a `<br/>` written in a label as an open `<br>`. That string is
not well-formed XML, so the strict `image/svg+xml` parse in
`normalizeSvgSize` yields the parsererror document instead of an `<svg>`,
takes the `el.tagName !== 'svg'` early return, and hands the *unnormalized*
string back. The diagram `<img>` then gets it as a `data:` URI, which Blink
decodes as strict XML and rejects for the same reason — so the message shows
a broken image whose alt text reads "Mermaid diagram", with nothing thrown
and nothing written to any log.

Close HTML void tags before the markup reaches either XML parse. The pass is
generic rather than a `<br>` special case, because the same class of input
reaches `<hr>`, `<img>`, `<input>`, …, and it is idempotent: already-closed
tags and non-void tags (including names that merely start with a void tag,
such as `<break>`) pass through untouched.

Fixes #133089

Verified by replaying 32 real ```mermaid fences from a session database
through the app's own renderer chunks in Electron 40.10.2 / Chromium 144:
24/32 fail before this change — every failure has `<br/>` in a label, with a
perfect 1:1 correlation — and 31/31 renderable diagrams succeed after it. The
32nd is an invalid Mermaid source that correctly keeps falling back to its
source block.
2026-10-09 11:57:18 -05:00
Jeffrey Quesnelle
e0550c97bb Merge pull request #135438 from NousResearch/fix/local-recs-weak-hardware
fix(local-models): stop recommending the 27B on hardware that can't run it well
2026-10-09 11:19:21 -04:00
Ben Barclay
0670ba4524 fix(tui_gateway): a settled client-gone interrupt beats the wakeup-schedule exemption
An interrupted detached turn sets the client-gone and turn-cancel latches. If
the active /loop or /heartbeat then re-armed the orphan timer after the turn
settled, neither latch ever cleared: no tick could claim the turn and every
reattach was refused with 4009, so the loop never reached its budget and the
session stayed pinned. Collect the settled session as before instead.

Also: TTL eviction checks the cheap clock before the store-reading exemptions,
and the heartbeat branch gets its own reaper tests (active local pins; paused,
cleared or gateway-owned releases).
2026-10-09 09:35:31 -04:00
Ben Barclay
b8878816b0 docs(loops): soften backend-lifetime wording 2026-10-09 09:35:31 -04:00
Ben Barclay
4bb139921f fix(tui_gateway): keep a detached session alive while it owns an active /loop or /heartbeat
The per-session notification poller is the only driver of a Desktop/TUI
(route-less) /loop or /heartbeat. When the client disconnects, the WS-orphan
reaper collects the idle session ~20s later and the TTL/LRU reapers can
collect it after that; either stops the poller, so the schedule freezes
(status still 'active') until a client reattaches and the overdue tick fires.

Treat an active, non-gateway-routed loop or heartbeat like live delegated
work: the orphan reap re-arms instead of popping the session, and the TTL and
session-cap reapers skip it. Gateway-routed schedules are fired by the
gateway's own scanner and do not pin the session. The exemption is bounded by
the loop's tick budget and ends on stop/pause. Memory-trim quiescence is
unchanged: an idle looping session does not block a trim.
2026-10-09 09:35:31 -04:00
Teknium
73162b00ee fix(update): a Desktop-only Node dependency failure no longer blocks the TUI and web UI
Every source update installs Node dependencies as one npm ci over ui-tui,
web and, when a built desktop app is present, apps/desktop. Only
apps/desktop brings native addons (node-pty, electron), so a host whose
compiler cannot build them (Ubuntu 20.04's g++ 9 rejects -std=gnu++20)
failed the whole install and lost the TUI and web UI builds as well, with
"a source update could not be finished automatically" on every launch.

When the union fails and the desktop app is part of it, retry once without
apps/desktop: the TUI and web UI build, the desktop build is reported owed
("desktop dependencies failed", the line the hand-off scripts match), and
the update names `hermes uninstall --gui` for hosts that never run the
app. The same hint prints whenever a headless Linux update builds Desktop,
since such a host keeps rebuilding an app nobody launches.
2026-10-09 04:16:17 -07:00
teknium1
8bff64d6ed fix(memory): keep a runaway-recall ceiling when prefetch spilling is off
Without the opt-in, external recall is kept whole up to
max(10 x hooks.output_spill.max_chars, 100k chars) and still spills above
that, so one runaway provider can't overflow the context window and wedge
the session. Normal provider-budgeted recall (~16 KB for Honcho) is
unaffected.
2026-10-09 02:59:16 -07:00
Erosika
2327290b0d fix(memory): make external prefetch spilling opt-in 2026-10-09 02:59:16 -07:00
Teknium
93257fd315 test(gateway): process scan skips other uids' gateways unless root 2026-10-09 02:50:51 -07:00
Teknium
99b57a42c7 fix(gateway): ignore other Unix users' gateway processes in the process scan
hermes gateway restart --all (and status, cron's gateway check, the update
fleet sweep) matched gateway argv host-wide with no owner check, so a gateway
run by a different UID became a SIGTERM target ('Permission denied to kill
PID') and was reported as an unfolded per-profile gateway with
'hermes gateway migrate --multiplex' advice. Non-root callers now skip
processes another uid owns; root keeps the host-wide scan (sudo over a
User= system unit), and an unknown owner keeps the argv verdict.
2026-10-09 02:50:51 -07:00
Teknium
d2639c0dc8 fix(plugins): a linked plugins/<name> slot reads "already installed", not a bad manifest
A memory provider's own installer (mnemosyne-hermes install, its README's
manual `ln -s`) leaves ~/.hermes/plugins/<name> as a symlink into a venv. The
catalog install of the same name then failed in _sanitize_plugin_name with
"Invalid plugin name 'mnemosyne': resolves outside the plugins directory" and
was recorded as failure_class=manifest_invalid, though the catalog manifest is
valid (hermes plugins validate passes it). Name the link and its target, say how
to free the slot, and record already_installed.
2026-10-09 02:42:26 -07:00
Teknium
6a2909c6b1 fix(memory): a failed agent-start provider install is not retried by every process start
recover_at_startup tried the configured provider's catalog install once per
PROCESS, so a home whose install fails (PM resolve/clone error, offline) retried
and failed again on every `hermes chat -q`, cron run, gateway agent and Desktop
restart. Each attempt is a recorded hermes.extension.install.count failure:
hindsight logged 1048 failures over 204 failing install-days (~5 per day per
install, the retry-loop shape) after it left core.

The left-core migration already had the fix: a failure stamp under
<home>/cache gates startup attempts for an hour while `hermes update` always
retries. Move that stamp into memory_provider_migration and use it in
recover_at_startup too; the backed-off start still tells the user memory is
off and names the install command.
2026-10-09 02:42:26 -07:00
Teknium
7085fbf775 fix(tts): a failed synthesis no longer deletes an existing file
text_to_speech swept every path it synthesized into on failure, including
an output_path that already held a user's file. When the target already
exists, synthesize into a hidden sibling instead; the delivery step still
os.replace()s it over the target on success (overwrite contract kept),
and a failure sweeps only the sibling.
2026-10-09 02:34:03 -07:00
Teknium
a114e7a344 fix(memory): detect providers past the first 8 KB of __init__.py
The discovery heuristic only searched the first 8 KB of a plugin's
__init__.py for the provider contract, so a valid provider with a long
module docstring was invisible. Fall back to _defines_memory_provider
(AST parse, no import) when the cheap text search misses.
2026-10-09 02:33:35 -07:00
Teknium
ecf9655b5a refactor(desktop): move plugin-contract type re-exports out of the SDK barrel
Keeps apps/desktop/src/sdk/index.ts under its code-health line cap after the
ctx.pet type exports.
2026-10-09 02:04:56 -07:00
Teknium
ecb66f60dd feat(desktop): plugin SDK pet bubble (ctx.pet.say)
Plugins can now put a short plain-text line in the core pet's speech bubble
instead of locating the pet canvas in the app DOM and floating their own
overlay over it (pet-wallet, #135178).

- ctx.pet.say(text, { id?, tone?, ttlMs? }) -> disposer; ctx.pet.clear(id?);
  ctx.pet.visible (ReadableAtom<boolean>)
- host-owned rendering in PetBubble, in-window (plugin lines only) and in the
  pop-out overlay (lines ride the existing pet-state IPC push)
- plain text, 120-char cap, control/bidi chars stripped, plugin-name label,
  TTL 6 s default (1-30 s), 3 live lines and 10 says/10 s per plugin
- core error / waiting states keep the bubble; nothing shows without a pet
- every line a plugin has up is cleared on unload/disable/reload
- docs: API section, migration-table row for pet-wallet, SDK exports
2026-10-09 02:04:56 -07:00
Teknium
66e0cee526 fix(browser): end timeout=None captured waits when the supervisor loop closes
A stop racing CapturedCDP.call() can close the supervisor loop before the
queued _send runs; run_coroutine_threadsafe's future then never resolves and
fut.result(timeout=None) hangs the consumer thread forever. Poll the unbounded
wait and raise CapturedCDPInvalid once the loop is closed. Fold the salvaged
validation tests into the dispatch file (one fixture, no F811), and tighten
them: the deadline test stalls inside the result grace, socket close asserts
CapturedCDPInvalid, the async validator asserts the refusal message.
2026-10-09 02:04:29 -07:00
web3blind
aad11beae0 fix(browser): fence captured CDP dispatch and retain late replies
# Conflicts:
#	tools/browser_supervisor.py
#	tools/browser_supervisor_capture.py
2026-10-09 02:04:29 -07:00
Teknium
acabfabf41 fix(mcp): a failed OAuth catalog install from a card or the agent says why, instead of exception
The connection-card / manage_connections install of an OAuth catalog entry runs the probe on a
worker thread; `mcp_oauth.start` then rebuilt the worker's error as a bare RuntimeError from its
text, dropping the `failure_class` `_probe_single_server` had tagged. Every pre-authorization
failure (empty or schemeless URL, unreachable host, 404 endpoint, refused client registration)
was recorded as `exception:RuntimeError` -> `exception`.

- run_worker classifies the original exception with probe_failure_class and stores the class on
  the flow; start() re-tags the RuntimeError it raises with it.
- probe_failure_class reads InvalidMcpUrlError (not http(s)://host) as config_invalid.
- _require_rendered_remote tags an unset ${VAR} in url/headers as missing_credentials.
- the "server responded but no token" refusal is auth_required.
- a connect_failed message that does not name the server gets a one-line next step
  ("Could not connect to 'n8n-official' (Not Found). Check its URL ...").

n8n-official is the only catalog entry whose URL is a user-supplied `${VAR}`, so it is the only
one where these user-side errors happen before authorization.
2026-10-09 02:04:02 -07:00
xielevi
5f045f842a catalog: add dashboard-auth-feishu 2026-10-09 00:59:00 -07:00
Matt Urenovich
3d26dfe376 feat(plugin-catalog): bump hermes-pickup to 0.2.0 2026-10-09 00:58:28 -07:00
Robby Czesany
fc2a5e8ff4 fix(plugin-catalog): bump web-search-plus to 4.3.5 2026-10-09 00:57:56 -07:00
teknium1
08f0796c47 chore(catalog): merge-side review chores for enchanted-composer (sweep 1009) 2026-10-09 00:57:26 -07:00
Deadtrix21
4db683291b catalog: re-pin Enchanted Composer after review 2026-10-09 00:57:26 -07:00
Zero2
4483288f92 catalog: add Enchanted Composer 2026-10-09 00:57:26 -07:00
teknium1
b7c5ca9138 chore: map contributor email for silentpr0 2026-10-09 00:56:56 -07:00
teknium1
a0c95a95f5 chore(catalog): merge-side review chores for redline (sweep 1009) 2026-10-09 00:56:56 -07:00
zero
6d0a823ae1 plugin-catalog: redline re-pin to 6fbb0f9 (review fixes) 2026-10-09 00:56:56 -07:00
silentpr0
26553dca90 feat(plugin-catalog): add redline plugin 2026-10-09 00:56:56 -07:00
teknium1
1caaef59d8 chore: map contributor email for hellohanchen 2026-10-09 00:56:25 -07:00
teknium1
b0af3e17b6 chore(catalog): merge-side review chores for huddo (sweep 1009) 2026-10-09 00:56:25 -07:00
Han Chen
c0c4044139 plugin-catalog: huddo 0.7.1 (re-pin to a86d3aa) 2026-10-09 00:56:25 -07:00
Han Chen
ed021a2dc2 plugin-catalog: add huddo 2026-10-09 00:56:25 -07:00
Teknium
ac6e7cc1c2 Merge pull request #133736 from anpicasso/catalog/cursor-provider-v0.3.5
fix(plugin-catalog): bump cursor-provider to v0.3.6
2026-10-09 00:56:22 -07:00
teknium1
6498baccdd chore: map contributor email for raaaas 2026-10-09 00:55:55 -07:00
teknium1
a3b56573df chore(catalog): merge-side review chores for agent-batch (sweep 1009) 2026-10-09 00:55:55 -07:00
raas
86f680d1e0 catalog: agent-batch — one required credential, real phasing, re-pinned sha
Follows the review on the plugin at 70fc4df6: requires_env trimmed to GITHUB_TOKEN
(the other four are optional config, and AGENT_BATCH_STATE is a directory override,
not a secret), the two agent tools the plugin now registers are declared, the
description states what actually phases the list, and the free-runner claim corrected
to the runners' real auth paths. Re-pinned to 064afc5d.
2026-10-09 00:55:55 -07:00
raas
b9add1d54d catalog: add agent-batch (owner-submitted) 2026-10-09 00:55:55 -07:00
teknium1
27e971d829 chore(catalog): merge-side review chores for openviking (sweep 1009) 2026-10-09 00:55:24 -07:00
ehz0ah
90773cce2d chore(catalog): pin merged OpenViking 2.1.1 release 2026-10-09 00:55:24 -07:00
ehz0ah
c9a15f6b53 chore(catalog): keep OpenViking release update in the catalog entry 2026-10-09 00:55:24 -07:00
ehz0ah
3dd14fb9af fix(catalog): match OpenViking general hook metadata 2026-10-09 00:55:24 -07:00
ehz0ah
fb5fa9c18f chore(catalog): refresh OpenViking documentation pin 2026-10-09 00:55:24 -07:00
ehz0ah
fddaa7ed4a docs(catalog): clarify OpenViking managed cloud setup 2026-10-09 00:55:24 -07:00
ehz0ah
5fd40ad8d3 docs(catalog): simplify OpenViking description and refresh guide 2026-10-09 00:55:24 -07:00
Hao Zhe
20a627a451 chore(catalog): align reviewed documentation pin 2026-10-09 00:55:24 -07:00
Hao Zhe
2b9d7c74ac chore(catalog): publish OpenViking 2.1.1 installer policy 2026-10-09 00:55:24 -07:00
Hao Zhe
6532f07221 feat(catalog): refresh OpenViking pin and honor display titles 2026-10-09 00:55:24 -07:00
kuehnberger
07abb626ef Bump qdrant plugin catalog pin to 0.1.8 (display levels), fix display-knob wording
Pins the qdrant memory provider at f65e62d (0.1.8), which adds display.level
(off | summary | verbose) for the recall indicator. The description's
previously-unqualified 'progress display (off/minimal/verbose)' sentence is
replaced: it named the older top-level progress knob, which is now easily
confused with the new display.level ladder. Both are stated with their own
value sets and what each gates.
2026-10-09 00:50:41 -07:00
teknium1
bf1b054ad0 chore(catalog): quote hermes-telemetry version 2026-10-09 00:50:41 -07:00