Commit graph

15123 commits

Author SHA1 Message Date
Teknium
5ba2d167ba
Revert "fix(agent): release pool FDs on owning-thread client close (#61979)" (#62141)
This reverts commit cd7a8dfde0.
2026-07-10 19:12:32 -07:00
ethernet
5e849942c3 feat(dev): add isolated sandbox script for local dev
scripts/desktop-sandbox.sh runs a Hermes desktop instance in an isolated
sandbox — separate HERMES_HOME, separate Electron userData, and a
distinct
app name (HERMES_DESKTOP_APP_NAME) so it doesn't compete with the main
desktop instance's single-instance lock.

Two modes:
- Ephemeral (default): temp dir, cleaned up on exit
- --persistent: stored under .hermes-sandbox/ in the worktree git root,
  survives restarts for repeat testing

In the Nix devShell the script is available as 'sandbox'.

Also makes APP_NAME overridable via HERMES_DESKTOP_APP_NAME in main.ts —
app.setName() runs before requestSingleInstanceLock(), so the overridden
name changes the lock key. collectRelaunchEnv already preserves
HERMES_DESKTOP_* vars through self-update relaunches; test updated to
cover the new env var.
2026-07-10 18:51:49 -04:00
brooklyn!
291eae63b7
Merge pull request #62016 from NousResearch/bb/desktop-vibe-hearts
feat: vibe reactions — floating hearts on affection, across CLI/TUI/desktop
2026-07-10 16:14:27 -05:00
Brooklyn Nicholson
1fa3886bce chore(desktop): remove the DEV Shift+H heart preview
The real trigger (core `reaction` event on affectionate messages) is live, so
drop the dev-only hotkey and its always-mounted listener.
2026-07-10 16:09:23 -05:00
ethernet
fc977f62bc fix(desktop): remove old .js files
we built .ts into .js for a minute there and dumped em in src, and those
old .js files are getting resolved over top of the ts updated ones so
desktop clients don't update.

just --clean the old files so there's never a conflict :3
2026-07-10 17:05:08 -04:00
ethernet
f7c9feb395 fix(desktop): only show slash popover when / is first char
The SLASH_TRIGGER_RE regex used (?:^|[\s]) as its left anchor, so typing
a / anywhere in the message (e.g. "hello /") opened the slash command
popover — even though slash commands only execute at the beginning of a
message. Anchor the regex strictly at position 0 (^) so the popover only
appears when / is the first character, matching the actual execution
semantics. The @-mention trigger is left untouched since those work
anywhere in the text.
2026-07-10 16:14:50 -04:00
ethernet
b8880f1245 fix(desktop): type-check electron/ in CI typecheck
removing tsc -b from the build script (previous commit) also removed
the only step that type-checked the electron/ directory — the CI
typecheck job runs tsc -p . --noEmit, which uses tsconfig.json whose
include is only ["src", "../shared/src"], so electron/ was silently
uncovered. extend the typecheck script to also run against
tsconfig.electron.json so electron/ stays type-checked in CI.
2026-07-10 14:06:51 -04:00
ethernet
db8772a062 fix(desktop): don't emit js files when we build desktop 2026-07-10 14:06:51 -04:00
Teknium
b9b463f3bd
feat(security): expose deterministic tool output risk (#61793)
* feat(security): expose deterministic tool output risk

* fix(security): emit output-risk events only for findings
2026-07-10 07:58:12 -07:00
Teknium
35d777df07 chore: map WilsonKinyua release attribution 2026-07-10 07:47:10 -07:00
Wilson Kinyua
1a2f3aea9a fix tui finalize persist drop conversation_history so disconnect saves chat
finalize passed conversation_history=history aliasing the snapshot so flush
skipped every message and wrote nothing. now flush _session_messages via
marker dedup like gateway shutdown. add real db e2e tests.
2026-07-10 07:47:10 -07:00
giggling-ginger
cd7a8dfde0 fix(agent): release pool FDs on owning-thread client close (#61979)
force_close_tcp_sockets stayed shutdown-only after #29507 to avoid
cross-thread FD recycle. That left CLOSED sockets unreclaimed when
httpx.close() skipped already-shutdown sockets under long-lived
gateways (~1 CLOSED fd / 6 min via proxy).

Add release_fds= for the owning-thread dispose path only; abort still
defaults to shutdown-only.
2026-07-10 07:28:39 -07:00
PRATHAMESH75
9b72995a1d fix(cron): never stale-remove a one-shot whose run is still alive
get_due_jobs()'s one-shot stale-entry recovery (#38758) treated an
expired run_claim (#59229) as proof the claiming tick died, but a run
stalled on network I/O — or a laptop asleep mid-run — legitimately
outlives the TTL while very much alive. The recovery then deleted the
job record mid-flight: list showed the job gone, and when the run
finished mark_job_run() found nothing to update, so last_run_at /
last_status / last_delivery_error were never recorded.

Two guards, per the liveness signals available:

- Same process (the common single-gateway case): before removing a
  dispatch-limit-reached one-shot, consult the scheduler's running set
  via a lazy import; if the job is still running here it is slow, not
  stale — keep the entry.
- Cross process: run_job's monitor loop now refreshes run_claim.at
  every 60s while the run is alive (including under
  HERMES_CRON_TIMEOUT=0, which previously blocked without polling), so
  an expired claim really does mean the owner died and the TTL stays a
  dead-owner detector.

Fixes #62002
2026-07-10 07:28:33 -07:00
kshitijk4poor
90bd5b0f9b test(telegram): mirror PTB errors in heartbeat recovery 2026-07-10 19:28:03 +05:30
liuhao1024
97fb9e1f62 fix(telegram): classify PTB heartbeat transport errors 2026-07-10 19:28:03 +05:30
kshitijk4poor
54e1864577 fix(acp): unwrap web extract object titles 2026-07-10 19:14:06 +05:30
kshitijk4poor
0b753d8918 fix(display): harden fallback label formatting 2026-07-10 19:14:06 +05:30
kshitijk4poor
c2a40b2dc9 fix(web): handle short extract provider results 2026-07-10 19:14:06 +05:30
kshitijk4poor
459cf3402b fix(web): preserve extract result input order 2026-07-10 19:14:06 +05:30
kshitijk4poor
e640bb5e18 test(web): cover model-facing dict URL dispatch 2026-07-10 19:14:06 +05:30
kshitijk4poor
de33c2413b fix(web): harden extract input and display boundaries 2026-07-10 19:14:06 +05:30
liuhao1024
7ae9faecf7 fix(tools): handle dict URLs in web_extract display and tool processing
When web_search results are passed directly to web_extract, the URLs
field contains dict objects (e.g., {"url": "...", "title": "..."})
rather than plain URL strings. Two code paths assumed URLs were always
strings and crashed:

- agent/display.py get_cute_tool_message for web_extract: tried to call
  url.replace() on a dict, causing AttributeError
- tools/web_tools.py web_extract_tool loop: tried regex search on a dict,
  causing TypeError

Both now extract the URL string from dict objects (url or href field) or
fall back to empty string, preserving the cosmetic display and allowing
the tool to process the URLs correctly.

Fixes #61693
2026-07-10 19:14:06 +05:30
kshitijk4poor
8727e67295 fix(runtime): preserve resolved fork metadata
Some checks are pending
CI / Detect affected areas (push) Waiting to run
CI / Python tests (push) Blocked by required conditions
CI / Python lints (push) Blocked by required conditions
CI / TypeScript (push) Blocked by required conditions
CI / Docs Site (push) Blocked by required conditions
CI / Deny unrelated histories (push) Blocked by required conditions
CI / Check contributors (push) Blocked by required conditions
CI / Check uv.lock (push) Blocked by required conditions
CI / Lint Docker scripts (push) Blocked by required conditions
CI / Build&Test Docker image (push) Blocked by required conditions
CI / Supply-chain scan (push) Blocked by required conditions
CI / OSV scan (push) Waiting to run
CI / All required checks pass (push) Blocked by required conditions
CI / CI timing report (push) Blocked by required conditions
Deploy Site / deploy-vercel (push) Waiting to run
Deploy Site / deploy-docs (push) Waiting to run
2026-07-10 18:50:28 +05:30
kshitijk4poor
97e9c64664 fix(runtime): preserve resolved fork metadata 2026-07-10 18:32:32 +05:30
infinitycrew39
f39c88befb test(curator): assert review fork forwards pool and overrides
Regression test that _run_llm_review passes credential_pool and request_overrides from resolve_runtime_provider into the curator AIAgent fork.
2026-07-10 18:32:32 +05:30
infinitycrew39
304cdbdc77 fix(curator): forward credential pool from runtime resolution
Curator review forks now pass credential_pool and request_overrides from resolve_runtime_provider into AIAgent so pool-backed custom providers can rotate credentials on 401 like main chat.
2026-07-10 18:32:32 +05:30
kshitijk4poor
d37090ac36 test(tui): cover profile-local MCP discovery 2026-07-10 18:09:17 +05:30
HexLab98
623165a640 fix(tui): discover MCP tools in slash workers 2026-07-10 18:09:17 +05:30
gigakun3030
dfdc3156fb
fix(models): remove unavailable OpenCode Zen free models (#61163) 2026-07-10 05:25:50 -07:00
kshitijk4poor
8fa0d8bbbb test(auth): pin runtime routing persistence on failure 2026-07-10 17:50:43 +05:30
kshitijk4poor
0e67c7231d fix(auth): validate and persist shared Nous routing 2026-07-10 17:50:43 +05:30
kshitijk4poor
03b8a00e26 fix(auth): recompute Nous routing after shared recovery 2026-07-10 17:50:43 +05:30
Sami Rusani
ca6513542d fix(auth): recover runtime Nous token from shared store 2026-07-10 17:50:43 +05:30
Brooklyn Nicholson
3aaf7e3876 feat(desktop): TikTok-style vibe hearts on a reusable particle system
Add a glyph-agnostic ParticleField (float-up + organic sway/bank + springy
pop-in), skinned as pink pixel hearts. Hearts play on the pet when one is out
(in-window or popped out) and celebrate alongside; otherwise they rise from the
composer. A generic $petReaction bus mirrors the burst to the pop-out overlay
window so it reacts even while the app is minimized.

Consume the core `reaction` event to fire hearts on affectionate messages. DEV
Shift+H previews a burst.
2026-07-10 05:42:14 -05:00
Brooklyn Nicholson
fbefb5c075 refactor(tui): drive the vibe heart from the core reaction event
Replace the client-side GOOD_VIBES_RE detection with the backend `reaction`
event: on it, flash the status-bar heart and the pet's celebrate pose. Detection
now lives once in the core, so the TUI, CLI, and desktop stay in sync.
2026-07-10 05:42:08 -05:00
Brooklyn Nicholson
0e2adf9dad feat(gateway,cli): emit + consume the reaction signal
tui_gateway forwards reaction_callback as a `reaction` event (shared by the TUI
and the desktop app). The interactive CLI wires reaction_callback to flash the
pet's celebrate ("jump") pose — the CLI's analogue of hearts.
2026-07-10 05:42:04 -05:00
Brooklyn Nicholson
422d9da9bd feat(agent): core affection reaction detector + reaction_callback
Add a token-free, curated affection matcher (agent/reactions.py) — the single
source of truth for detecting user "vibes" (ily / <3 / good bot / heart emoji).
No model call, no tokens. Generalized to return a reaction *kind* so future
reactions can ride the same signal.

Wire an opt-in AIAgent.reaction_callback that fires from build_turn_context on
the incoming user message. It never touches the conversation (cache-safe) and
never fatal — a purely cosmetic side-beat each host can consume.
2026-07-10 05:41:59 -05:00
brooklyn!
caf557be5b
Merge pull request #61973 from NousResearch/bb/desktop-tip-stuck
fix(desktop): stop Tip from sticking open and blocking clicks
2026-07-10 04:03:15 -05:00
Brooklyn Nicholson
29f3dc0809 fix(desktop): stop Tip from sticking open and blocking clicks
Radix's hoverable-content grace area can leave tips stuck over Electron drag regions; disable it and make tip content pointer-events-none so open state tracks the trigger only.
2026-07-10 04:00:32 -05:00
brooklyn!
a9f3f08700
Merge pull request #61916 from NousResearch/bb/desktop-gateway-switch-ux
feat(desktop): soft gateway switch + gateway-settings polish
2026-07-10 03:16:09 -05:00
brooklyn!
79a104d037
Merge pull request #61912 from NousResearch/bb/salvage-55402-desktop-cloud-mode
feat(desktop): Hermes Cloud connection mode (salvage of #55402)
2026-07-10 03:15:59 -05:00
Brooklyn Nicholson
b3bde1fbee feat(desktop): soft gateway switch + gateway-settings polish
Switching connection mode (local / cloud agent / remote) no longer
full-window-reloads into the cold-boot CONNECTING screen. The primary
backend is torn down in place (no renderer reload); the shell + Settings
stay up while session lists are wiped so sidebar skeletons retrigger, then
the socket re-dials and config/sessions refresh. Cold-boot CONNECTING
latches off after the first successful boot; the intentional teardown
suppresses the backend-exit toast. Dev affordance: a "Preview soft switch"
button under Gateway diagnostics (Electron has no ?query= entry).

Gateway settings UI brought in line with the rest of Settings:
- Mode cards use the shared selectableCardClass on an equal-height
  auto-rows-fr grid, stacking 1→3 (never an orphaned 2+1); titles wrap
  instead of truncating.
- Remote gateway's auth detail moves into a ? tooltip in the title; drop
  the redundant "connects to the one you choose" from the cloud card.
- textStrong buttons force px-0 so the underline sits flush with the label.
- Tooltip chip uses box-decoration-break: clone so the background hugs each
  wrapped line (bg only on the text), capped at max-w-64.

Fully i18n'd (en + zh; ja/zh-hant inherit via defineLocale).
2026-07-10 02:57:02 -05:00
kshitijk4poor
a0032f5f92 fix(routing): preserve profile and delegation parity 2026-07-10 13:10:45 +05:30
Gille
3aeaf3755d fix(nous): forward provider routing through Portal 2026-07-10 13:10:45 +05:30
kshitijk4poor
69f1460c3d test(model): isolate custom provider discovery 2026-07-10 13:10:30 +05:30
kshitijk4poor
7628f2770a test(model): assert explicit catalogs never probe 2026-07-10 13:10:30 +05:30
kshitijk4poor
0629caac62 fix(model): derive catalog policy from declarations 2026-07-10 13:10:30 +05:30
luyifan
5f00f36ba9 fix(model): probe no-key custom provider catalogs 2026-07-10 13:10:30 +05:30
brooklyn!
46cf87be16
Merge pull request #61935 from NousResearch/bb/salvage-59902-bootstrap-repin
fix(desktop): prevent bootstrap stale commit repin on existing checkouts
2026-07-10 02:38:44 -05:00
Brooklyn Nicholson
6207d68948 fix(desktop): prevent bootstrap stale commit repin on existing checkouts
Old packaged Desktop apps re-entering bootstrap against an existing
~/.hermes/hermes-agent were still passing the baked-in --commit pin, which
detached the managed checkout back to the app stamp (e.g. 0.15.1) after
hermes update had already moved it forward.

Skip the packaged commit pin when activeRoot already has git metadata;
keep branch args and fresh-install commit pinning unchanged. Port of
#59902 onto the post-ts-ify bootstrap-runner.ts.

Co-authored-by: helix4u <4317663+helix4u@users.noreply.github.com>
2026-07-10 02:29:58 -05:00