Commit graph

1634 commits

Author SHA1 Message Date
Teknium
89130bf1f7 chore(release): map auxiliary runtime contributors 2026-07-17 09:08:30 -07:00
kshitij
f32191fd52
Merge pull request #66254 from kshitijk4poor/chore/author-map-maartendmt
chore: add MaartenDMT to AUTHOR_MAP
2026-07-17 18:48:27 +05:30
Teknium
9fc0074bac fix(gateway): unify reset boundaries vs recovery — promote accidental ends, honor mode=none, adapter-aware resume guidance
Unifies the two gateway subsystems that were fighting each other: the
'never lose a session' recovery machinery (#54878 stale-route self-heal,
find_latest_gateway_session_for_peer reopening agent_close/ws_orphan_reap
rows) and the session reset/expiry machinery (expiry watcher, /new,
/resume, resume_pending freshness gate).

The unified contract:
- INTENTIONAL boundaries (expiry finalization, auto-reset, /new,
  /resume switch) are recorded durably via promote_to_session_reset(),
  which upgrades accidental recoverable end_reasons (agent_close,
  ws_orphan_reap) to the explicit boundary while preserving other
  explicit reasons (compression, etc.). Recovery then correctly refuses
  to resurrect them.
- ACCIDENTAL ends (crash, cleanup bug, mistaken reaper) stay
  recoverable — genuine crash recovery is untouched.

On top of the cherry-picked contributor commits:
- promote_to_session_reset widened to ws_orphan_reap + parameterized
  reason so auto-reset paths stay auditable (idle/daily/suspended/
  resume_pending_expired) (#61220, #61993, #63539)
- get_or_create_session auto-reset, reset_session (/new), and
  switch_session (/resume) all write through the promote path — the
  first-reason-wins end_session no-op could previously leave a reset
  session resurrectable behind a stale agent_close row (#61993)
- resume_pending freshness gate now honors session_reset.mode=none:
  explicit opt-out of automatic resets also opts out of the zombie
  gate (#61052)
- resume recovery note extracted to build_resume_recovery_note() and
  made adapter-aware via a new interactive_resume capability flag:
  webhook/api_server auto-resume turns now CONTINUE the interrupted
  task instead of emitting an unanswerable 'session restored'
  acknowledgement that abandoned the work (#57056)
- tests updated to call the real note builder instead of mirroring it

E2E-validated against a real SessionDB + SessionStore in a temp
HERMES_HOME: expiry->agent_close->no-resurrection, /new promote,
crash recovery preserved, mode=none opt-out, routing-table flag sync.
2026-07-17 04:51:39 -07:00
Teknium
14ea8de763 fix(agent): harden non-finite wait recovery
Only advertise finite watchdog deadlines that are still in the future, exercise the full MoA heartbeat path, and register the salvaged contributor attribution.
2026-07-17 04:46:59 -07:00
kshitijk4poor
ebc32bfcf7 chore: add MaartenDMT to AUTHOR_MAP for PR #65637 salvage 2026-07-17 16:34:34 +05:30
Teknium
779019ef7d feat(agent): add display.show_commentary toggle for Codex commentary channel
Commentary delivery is on by default; users who find the extra mid-turn
narration noisy can set display.show_commentary: false to restore the
previous behavior (commentary routed to the reasoning channel, visible
only with show_reasoning).

- hermes_cli/config.py: display.show_commentary default true
- agent/agent_init.py: wire config -> agent.show_commentary
- run_agent.py: gate structured commentary extraction on the flag
- agent/codex_runtime.py: gate live-stream commentary callback (falls
  back to legacy reasoning-channel routing when off)
- docs + 2 tests (interim path off, live stream fallback)

Also adds AUTHOR_MAP entries for davidrobertson and 100yenadmin.
2026-07-16 23:27:12 -07:00
Thatgfsj
ef1c622105 fix(title): prevent stale background title generation from reloading unloaded Ollama models
Add a runtime_validator callback to generate_title() / auto_title_session()
/ maybe_auto_title(). Callers snapshot the session's model+provider when
spawning the background titler; the validator runs right before the LLM
request and skips it silently when the live runtime no longer matches —
so a stale title request can't reload a model that strict_single_load
already evicted after a user model switch. Fail-open: a raising validator
never disables titling.

Wired at all four call sites (cli, gateway, tui_gateway, acp_adapter).

Surgical reapply of PR #19137 (base was 8k+ commits stale; the original
patch predates the pinned-language prompts, the atomic-write helper, and
the moved TUI/ACP call sites). Original work by @Thatgfsj. Closes #19027.
2026-07-16 23:07:13 -07:00
Teknium
61be8b3112 chore(release): map seagpt noreply identity for PR #62983 salvage 2026-07-16 22:54:09 -07:00
Teknium
7facf63ae7 fix(title): reconcile atomic auto-title writes with collision dedup retry
Combines the two salvaged fixes so they compose instead of conflict:
_persist_session_title (#50575) now writes through set_auto_title_if_empty
(#51483) when the store provides it — the collision-dedup retry and the
manual-/title race protection apply together. Predicate failure (a manual
title landed while generation was in flight) returns None: nothing written,
no callback. Legacy stores without the atomic method keep the plain
set_session_title path, including the vanished-session RuntimeError.

Tests cover both store shapes plus the race-skip path; E2E verified against
a real SQLite SessionDB (collision -> 'Weekly Report #2', manual title
preserved, cron dedup, blank guard). AUTHOR_MAP entry for rasitakyol.
2026-07-16 22:39:47 -07:00
Teknium
04d84df63c fix(honcho): memoize timeout staleness check + host-aware status cadence
Follow-ups for the consolidated salvage:
- Memoize the config.yaml-derived timeout on the file's mtime_ns so the
  rebuild-on-timeout-change check from PR #57437 costs one stat() per
  get_honcho_client() call instead of a full YAML load on the hot path.
- hermes honcho status now displays the host-block-resolved
  dialecticCadence (remnant from PR #63776, whose runtime fix landed
  in #62290).
- AUTHOR_MAP entries for the salvaged contributor emails.
2026-07-16 22:25:22 -07:00
Teknium
8222b16785 fix(title): follow-ups for salvaged #37349 — lazy config import, guard ordering, config example
- Make the config imports lazy inside _auto_title_enabled(), matching the
  existing _title_language() pattern (title_generator is imported from agent
  code paths where a module-level hermes_cli import risks circularity).
- Check the enabled flag after the cheap first-exchange guard in
  maybe_auto_title so config isn't read on every turn of a long session.
- Repoint the two new tests at the real import site.
- Document the key in cli-config.yaml.example and merge the enabled flag
  into the existing title_generation block in configuration.md.
- AUTHOR_MAP entry for the contributor.
2026-07-16 22:24:45 -07:00
Gille
7cb2d2cd4a
fix(auth): detect configured providers absent from registry (#66017)
* fix: detect env-var-configured providers absent from PROVIDER_REGISTRY

is_provider_explicitly_configured() only checked PROVIDER_REGISTRY (a
manually-maintained dict) for env-var names. Providers that exist solely
in the models.dev catalog — e.g. openrouter — were never recognised as
explicitly configured, so they were filtered out of the desktop model
picker even when their API key was set in .env.

Add a fallback to get_provider() (which reads the models.dev catalog)
when PROVIDER_REGISTRY returns None. Both ProviderConfig and ProviderDef
expose .auth_type and .api_key_env_vars with the same shape.

* test: keep OpenRouter provider gate assertion behavioral

* chore(release): map salvaged OpenRouter contributor

---------

Co-authored-by: zzpigpinggai <zzpigpinggai@users.noreply.github.com>
2026-07-16 22:56:45 -04:00
Gille
1f7d2be22f
fix(install): detect Git Bash Mandatory ASLR failures (#64651) 2026-07-16 22:46:46 -04:00
Erosika
2ad6ab17e3 fix(honcho): enforce recall latency and budget contracts 2026-07-16 12:48:48 -07:00
Erosika
29e0471708 fix(honcho): update SDK and restore CI coverage 2026-07-16 12:48:48 -07:00
brooklyn!
7d27a31ce7
feat(dashboard): isolate turns in compute host (#65895)
Add the flag-gated compute-host supervisor, delta/control protocol, PPID orphan guard, inline fail-open path, synthetic GIL-heavy turn seam, and AC-4 certify harness.

Verified on current origin/main: 343 focused tests pass; Ruff and diff checks pass; 360s AC-4 run with six heavy lanes passes at 6.11ms serving p99 with zero stalls and valid load.

Co-authored-by: Kyzcreig <9063726+Kyzcreig@users.noreply.github.com>
2026-07-16 15:24:03 -04:00
Teknium
6cd5a2c5f7 chore(release): add sam7894604 to AUTHOR_MAP; widen /reasoning choices to max/ultra
The salvaged choices list predates the max/ultra effort levels (#62650);
add them so the Discord dropdown matches the canonical ladder. Discord
caps choices at 25 — we're at 11, plenty of headroom.
2026-07-16 08:58:34 -07:00
Teknium
8462764367 chore(release): map bare-noreply test-commit identity for PR #62028 salvage 2026-07-16 08:47:10 -07:00
Teknium
007cd15132 chore(release): map focusedmiqa@gmail.com to m1qaweb in AUTHOR_MAP (PR #29290 salvage) 2026-07-16 08:02:47 -07:00
Teknium
4759362188 chore(release): add briandevans to AUTHOR_MAP for PR #64951 salvage 2026-07-16 07:57:51 -07:00
Teknium
6cc4691c86 chore(release): map otsune's noreply email in AUTHOR_MAP (PR #36019 salvage) 2026-07-16 07:33:14 -07:00
Teknium
7edaaf4682 chore: map nnnet noreply email in release AUTHOR_MAP (PR #36024 salvage) 2026-07-16 07:28:22 -07:00
Teknium
2fba721ab0 chore(release): map antydizajn's commit email for PR #36043 salvage attribution 2026-07-16 07:28:07 -07:00
Teknium
bb853b2e95 chore(release): map rlaehddus302's email in AUTHOR_MAP (PR #61985 salvage) 2026-07-16 07:17:55 -07:00
teknium1
3366204474 chore: AUTHOR_MAP entry for doxe0x (PR #50786 salvage) 2026-07-16 07:11:21 -07:00
Teknium
75c878217d fix(moa): route per-slot reasoning effort through the canonical parser
_clean_reasoning_effort kept its own whitelist that stopped at 'max',
silently dropping 'ultra' from MoA slot configs. Route it through
hermes_constants.parse_reasoning_effort — the same one-source-of-truth
fix the salvaged commit applies to the gateway — so future effort
levels can't drift here either. Docs updated to list ultra.

Follow-up to salvaged PR #64012.
2026-07-16 06:14:58 -07:00
teknium1
56e06d7ee9 chore(release): AUTHOR_MAP entries for Florian Burka (flewe) and Peter Skaronis (Peterskaronis) 2026-07-16 06:14:34 -07:00
Teknium
7a78342ab3 chore: add AUTHOR_MAP entry for shuangxinniao (PR #40127 salvage) 2026-07-16 05:56:22 -07:00
Teknium
5604d1852e chore(release): map aeyeopsdev noreply email in AUTHOR_MAP 2026-07-16 05:43:30 -07:00
Teknium
702473edbd chore(release): map jtstothard's email in AUTHOR_MAP (PR #63256 salvage) 2026-07-16 05:39:58 -07:00
Teknium
01d3268e02 fix(gateway): harden multiplex credential cluster salvage
Follow-ups on top of the cherry-picked cluster commits:

- slack: scope-authoritative app-token read — get_secret() with a
  narrow UnscopedSecretError fallback to os.getenv. Keeps @kohoj's
  correct semantics (scoped profile can never silently inherit the
  default profile's Socket Mode app) while fixing the regression where
  the default-profile startup loop and background reconnect rebuild,
  which call connect() unscoped under multiplex, would raise and
  fail-loop. Supersedes the 'or os.getenv' variant from #64461 which
  reintroduced the cross-profile fallback leak.
- test: unscoped-multiplex fallback regression test for connect().
- run.py: convert the last legacy self.adapters.get(source.platform)
  site (_rename_discord_auto_thread) to _adapter_for_source(source)
  so profile-routed Discord sources rename threads on the right
  adapter (from #57417's sweep).
- AUTHOR_MAP entry for @aguung.
2026-07-16 05:39:58 -07:00
teknium1
c82a196ea9 chore: AUTHOR_MAP entry for Code-suphub's second commit email (PR #44872 salvage) 2026-07-16 05:39:52 -07:00
teknium1
49d3fee0bd chore: AUTHOR_MAP entry for Code-suphub (PR #44872 salvage) 2026-07-16 05:39:52 -07:00
Teknium
07e537d8ea chore: AUTHOR_MAP entry for salvaged PR #65105 2026-07-16 05:08:56 -07:00
Teknium
b60c940d9e chore(release): map wesleion noreply email in AUTHOR_MAP
Attribution for salvaged PR #36049.
2026-07-16 04:53:08 -07:00
Teknium
a79b818360 chore(release): map kocaemre's email in AUTHOR_MAP (PR #36051 salvage) 2026-07-16 04:47:40 -07:00
Teknium
4851f894be chore: AUTHOR_MAP entry for salvaged PR #64935 2026-07-16 04:43:45 -07:00
szafranski
4a79305930 chore(release): map p.fabiszewski@gmail.com to szafranski in AUTHOR_MAP 2026-07-16 04:40:35 -07:00
Drexuxux
eb48e22106 chore: map drexux0@gmail.com in AUTHOR_MAP for contributor-attribution check 2026-07-16 04:40:23 -07:00
Teknium
244f70aae5 fix(agent): scope install-tree guard to fallback-picked cwds, allow cli/tui in-tree dev
Follow-up on the salvaged #64611 commit: the original guard blocked the
install tree unconditionally, which would have broken the legitimate
'developing Hermes from a source clone' CLI flow (launching hermes inside
the repo and getting its AGENTS.md as project context).

Refined policy:
- resolve_context_cwd(): validates configured paths (missing dir -> None +
  warning) but honors an EXPLICIT install-tree cwd verbatim — deliberate
  user choice.
- build_context_files_prompt(): blocks only the cwd=None -> os.getcwd()
  FALLBACK into the install tree, with a new allow_install_tree_fallback
  param. system_prompt.py passes it for platform cli/tui (launch dir is
  the user's real shell cwd there); desktop/gateway surfaces keep the
  guard (their fallback dir is self-spawned, never user-picked).
- Warning log names the resolved dir and the terminal.cwd remedy.

E2E-verified all five scenarios: desktop fallback blocked, in-tree CLI dev
keeps AGENTS.md, explicit install-tree cwd honored, invalid TERMINAL_CWD
falls to None then blocked, normal workspace loads.
2026-07-16 04:32:23 -07:00
Teknium
b4e4b5a43e fix(gateway): harden multiplex primary token gate — canonical platform map + unserved-platform warning
Follow-ups to @SAMBAS123's #64986 salvage:

- Replace the hardcoded token-platform set in _platform_has_bot_credential
  with PLATFORM_TOKEN_ENV_NAMES, a shared canonical map in gateway/config.py
  also used by the empty-token validation warning — one source of truth, so
  future token platforms can't silently bypass the gate or drift between
  the two sites.
- After secondary-profile startup, warn loudly for any platform skipped on
  the primary that no secondary profile ended up serving: an enabled
  platform with no credential anywhere is a config error, not a silent
  no-op.
- AUTHOR_MAP entry for the salvaged commit's author email.
2026-07-16 04:26:06 -07:00
Teknium
e2db5ebad5 chore: AUTHOR_MAP entry for nima20002000 (#36022 salvage attribution) 2026-07-16 04:25:19 -07:00
Teknium
5342f8613d chore: add AUTHOR_MAP entry for brendandebeasi (PR #29860 salvage) 2026-07-16 04:24:14 -07:00
kshitijk4poor
e0240d7bf7 chore: add marcelohildebrand to AUTHOR_MAP for PR #42346 salvage 2026-07-16 15:23:14 +05:30
Teknium
6ee40b65ba chore: add ya-nsh to AUTHOR_MAP 2026-07-16 01:28:13 -07:00
Teknium
094f2b55d3 chore: AUTHOR_MAP entry for 2751738943 (PR #54785 salvage) 2026-07-15 23:51:43 -07:00
ethernet
f8ddf4fd86
feat(ci): semantic package-lock.json diff as an upserted PR comment (#65206)
git diff on a lockfile is unreadable: npm reorders entries, rewrites
integrity hashes, and moves packages between nesting levels, so a
one-line package.json bump produces a thousand-line textual diff.

scripts/ci/lockfile_diff.py instead parses the `packages` map out of
both versions of every tracked package-lock.json (via `git show`),
reduces each to {install path: version}, and set-diffs the maps —
reorder/hash churn vanishes, leaving only actual version movement
(added / removed / updated, with nested dedup copies tracked
separately).

The lockfile-diff workflow posts the result as a Markdown table in a
PR comment gated behind a hidden marker: subsequent pushes PATCH the
existing comment instead of stacking new ones, and a push that reverts
all lockfile changes updates the comment to say so. Advisory only —
never fails on findings; fork PRs (read-only token) degrade to a
warning.

Wired through the ci.yml orchestrator with a new npm_lock lane in
classify_changes.py (fails open on .github/ changes per the existing
contract).
2026-07-16 03:18:15 +00:00
ethernet
f8b6d381e2
fix(nix): dirty-tree wrapper bug + filtered rebuild scope + overlay alias (#65237)
* fix(nix): fold makeWrapper line continuations into optionalStrings

When rev == null (any dirty-tree build), the empty optionalString
expansion left the previous line's trailing backslash dangling onto a
blank line, ending the makeWrapper command early and running
`--suffix PYTHONPATH ...` as its own shell command (`--suffix: command
not found`, exit 127). Clean trees passed CI; dirty trees with
extraPythonPackages failed — exactly the path the NixOS module
exercises.

The continuation now lives inside each optionalString (" \\\n  --set
..."), so the makeWrapper chain stays intact whether or not the
optional flags expand.

Verified by building with rev = null + extraPythonPackages =
[ pyfiglet ]: wrapper builds, PYTHONPATH suffix lands inside the
makeWrapper call, wrapped `hermes --version` runs, and the collision
check still executes (certifi correctly rejected).

* perf(nix): filter derivation sources to shrink rebuild scope

Every derivation previously saw the whole repo, so any file change
rebuilt everything. Each derivation now gets a filtered src with only
the files it consumes:

- lib.nix: derive npm workspace topology from the root package.json
  `workspaces` globs (single source of truth — a new workspace member
  is picked up with zero nix edits). pythonSrc (cleanSourceWith)
  excludes the JS workspace trees, docs/website, docker/.github,
  tests, nix/, flake.nix/flake.lock, root docs, and skills/ +
  optional-skills/. importNpmLock reads from a fileset-filtered
  npmRoot (root manifests + member package.jsons only).
- mkNpmPassthru takes `dirs` — the workspace dirs the package
  contains — and builds a per-package fileset src from them. web and
  desktop include apps/shared (file: dep). One shared
  `nix run .#update-npm-lockfile` replaces the per-package
  update_*_lockfile bins that only existed inside build sandboxes.
- python.nix: release venv loads the uv2nix workspace from pythonSrc.
  The editable venv keeps an unfiltered ./.. root —
  mkEditablePyprojectOverlay calls lib.path.splitRoot, which rejects
  a cleanSourceWith set, and the editable install reads the live
  checkout anyway.
- hermes-agent.nix: skills ship exclusively via HERMES_BUNDLED_SKILLS
  / HERMES_OPTIONAL_SKILLS (same mechanism as Homebrew packaging;
  setup.py's _data_file_tree returns [] for missing dirs), so
  SKILL.md edits no longer rebuild the venv. optional-mcps stays in
  the wheel — pyproject.toml lists its manifests as explicit
  data-files. Bundled assets are symlinked instead of copied, making
  the wrapper drv near-instant when only an input changed.
  __pycache__ filtered from bundled skills.
- checks.nix: find -L through the new symlinks; assert
  optional-skills presence + HERMES_OPTIONAL_SKILLS in the wrapper.
- run_tests.sh: fall back to $HERMES_PYTHON when no local venv
  exists, guarded by an `import pytest` probe (HERMES_PYTHON from a
  wrapped hermes binary points at the release venv, which has no
  pytest — without the guard every test file dies with "No module
  named pytest" while the runner exits 0).

Verified: nix flake check exit 0; built .#default .#tui .#web
.#desktop; SKILL.md and flake.nix edits leave the venv drvPath
unchanged; .py edits leave the tui drvPath unchanged; .tsx edits
leave the venv drvPath unchanged (and do change the tui drv);
scripts/run_tests.sh runs 299 tests green through both the venv and
HERMES_PYTHON paths, and rejects a pytest-less HERMES_PYTHON.

* refactor(nix): overlay aliases the flake's own package instead of re-instantiating

The overlay previously re-called callPackage against the consumer's
nixpkgs (final), so pkgs.hermes-agent could be a different derivation
than nix build .#default and the NixOS module's default — an untested
build matrix against arbitrary consumer nixpkgs versions, for a
package whose Python side is uv2nix-locked anyway.

Now the overlay is a pure alias for the flake's own locked package:
one callPackage site (packages.nix), everything else references it.
.override { ... } still works — callPackage's makeOverridable travels
with the derivation.

Verified: direct drvPath == overlaid drvPath; .override produces a
distinct drv.

* fix(nix): dedupe extraPlugins assertions, replace MESSAGING_CWD with terminal.cwd

- Delete the duplicated extraPlugins duplicate-name assertions block
  (same assertion declared twice back to back).
- Stop setting the deprecated MESSAGING_CWD env var, which made the
  module trip hermes' own startup deprecation warning. The working
  directory is now injected as terminal.cwd into the generated
  config.yaml; cfg.settings wins via recursiveUpdate, and container
  mode maps to the in-container mount path.
2026-07-15 21:45:35 -04:00
Ben Barclay
3f2a389c7e
fix(auth): apply newer hosted bootstrap session (#64612)
* fix(auth): apply newer hosted bootstrap session

* fix(auth): validate rebootstrap replacement seeds
2026-07-16 08:52:47 +10:00
ethernet
ef7aabd3d1 ci: add ci-reviewed label gate for CI-sensitive files 2026-07-16 01:42:02 +05:30