chore: sync fork with NousResearch upstream main - #97
Conversation
…parts DoS) tornado 6.5.7 is affected by GHSA-5w76-955r-9v8r (CVSS 8.7): parse_multipart_form_data splits the body unbounded before the max_parts check, so a request with a very large number of parts can exhaust memory. 6.5.8 caps the split at max_parts+1 so the flooding part is never materialized. uv lock --upgrade-package tornado on current main; only the tornado block changes (13 insertions / 13 deletions in uv.lock), no other package or marker moves. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QghbdVnZSkJbRRDxCSs2zr
…ct() retrying forever slack-sdk 3.44.1 contains the upstream fix for the aiohttp SocketModeClient zombie retry loop (slackapi/python-slack-sdk#1956, closing NousResearch#1913): connect() used 'while True:' and never checked self.closed, so once close() closed the shared aiohttp ClientSession, any connect/reconnect task in flight spun forever logging 'Failed to connect (error: Session is closed); Retrying...' every ping_interval. Observed in production on this repo's own Slack adapter: the gateway's socket watchdog (plugins/platforms/slack/adapter.py) heals wedged sockets by rebuilding the AsyncSocketModeHandler, but the orphaned connect() task from the pre-heal client kept retrying against the dead session indefinitely — 22k+ error lines per process per day while Slack itself remained connected. The adapter's teardown docstring already references slackapi#1913. 3.44.1 adds the self.closed exit; slack-bolt 1.30.0 declares slack_sdk>=3.38.0,<4, so the bump is compatible.
pyproject extras and the lazy installer must agree on the slack-sdk pin; the salvaged bump only touched pyproject.toml + uv.lock, so the `platform.slack` lazy-install spec would still have pulled 3.43.0.
…s testable The picked fix inlined the platform ternary inside terminalShellEnv(), which reads process.platform and can only be exercised by booting Electron. Lift it into a pure terminalLcCtype(env, platform) that takes the platform as data (root AGENTS.md: never fake the host OS) and pin the contract with one vitest: Linux reuses LANG, falls back to C.UTF-8, respects an explicit LC_CTYPE; macOS keeps the bare "UTF-8" it accepts. Red on origin/main (helper absent), green here.
…path too Same bug class as the wake-gate call fixed in the picked commit: when a caller invokes _build_job_prompt without a cached prerun_script, the sibling ran the job's script inline via _run_job_script(script_path) and dropped the job's configured workdir, so the script ran from the scripts-dir parent. Route it through _resolve_job_workdir like the no_agent and wake-gate sites already do. Sweep of every _run_job_script / _run_job_script_with_claim_heartbeat caller: _run_no_agent_job and cron/monitor.py already pass workdir; the wake-gate site is fixed by the salvaged commit; this was the last one.
…te fails `_append_to_sqlite` caught and debug-logged its own exceptions, so the outer handler in `mirror_to_session` never fired and every failed SQLite write was reported as a successful mirror. Callers (cron in_channel seed, send_message) had no way to know the transcript was never updated. Let the write helper raise; the caller already warns and returns False. Fixes NousResearch#10130
Windows-footgun ratchet for the file touched by this fix (no behaviour change).
`add_provider()` flipped `_has_external` and appended the provider before calling `get_tool_schemas()`. When schema loading raised, the broken provider stayed registered and the single-external slot was poisoned for the rest of the process: every later provider was rejected as "already registered". Materialize the schema list first; state changes only after it succeeds. Exception propagation is unchanged. Hand-port of PR NousResearch#9997 by @zhouhe-xydt onto the current add_provider() (the reserved-core-tool filter landed in between); one invariant test. Fixes NousResearch#9948
…_provider.py Windows-footgun ratchet for the file touched by this fix (no behaviour change).
…urces `_get_tool_usage()` merged `tool_name` rows and assistant `tool_calls` JSON with a GLOBAL per-tool max. That is right inside one session (both columns describe the same call) but wrong across sessions: a gateway session recording `tool_name` only plus a CLI session recording `tool_calls` only for the same tool reported 1 use instead of 2. Group both queries by (session_id, tool_name), reconcile with max per session, then sum across sessions. Port of PR NousResearch#9896 by @MonkeyLeeT onto the `_scoped` query layout; one invariant test covering disjoint sessions AND a paired session. Fixes NousResearch#9814
The pick returns the real result after a transport recovery instead of dropping it, but it also skipped the breaker bookkeeping. Application errors counting as strikes is the point of the breaker (3ff18ff, NousResearch#10447: a server answering errors made the model hammer it 8x in 10s). Route the recovered result through _record_call_outcome so the caller sees the tool's answer and the counter still moves the right way.
`build_tool_preview()`'s generic-key fallback and the cute-message helpers still truncated with a bare `text[:max_len - 3] + "..."`; for max_len 1-3 the slice goes negative and returns almost the whole string (27 chars for max_len=1). `_truncate_preview` already had the guard, so the two code paths disagreed. One truncation helper (`_tail_trunc`) with the guard, used everywhere; the head-truncating `_cute_path` gets the same clamp. Salvage of PR NousResearch#48483 by @HeLLGURD (current-code fix); the earliest reports and patches were NousResearch#9464 (@LarHope), NousResearch#9477 (@kagura-agent) and NousResearch#9497. Co-authored-by: LarHope <12761142+LarHope@users.noreply.github.com> Fixes NousResearch#9439
…_plist_if_needed Ports NousResearch#63762 forward onto current main per teknium1's review. refresh_launchd_plist_if_needed() logged the retry failure but still returned True and printed success. launchd_install() then unconditionally printed '✓ Service definition updated' even when the service was not registered with launchd (NousResearch#12882). 1. refresh_launchd_plist_if_needed(): return False after retry exhaustion so callers can distinguish failure from success. 2. launchd_install(): check the bool; on False print a warning instead of the success message. Per review: the warning now renders the reload-log location via display_hermes_home() (the existing lazy-import convention used elsewhere in this module for user-facing paths, e.g. the gateway.log path prints a few lines away) instead of a hardcoded ~/.hermes path, so named/custom Hermes home profiles show the correct location. Existing _retry_launchctl_bootstrap_until_registered() retry/EIO/ timeout/verify logic unchanged. 5/5 tests pass (4 ported + 1 new for the display_hermes_home fix).
…Research#12863) The repair branch in `systemd_install()` exits as soon as it rewrites an outdated unit and re-runs `systemctl enable`, bypassing `_ensure_linger_enabled()`. On headless Linux the command reports success, but the repaired user service still stops at logout. Call `_ensure_linger_enabled()` before the early return when the install is user-scoped, mirroring what the fresh-install path already does. Adds two regression tests in `tests/hermes_cli/test_gateway_linger.py`: - repair path (user scope) calls the linger helper - repair path (system scope) does not call it
Invariant test for NousResearch#9879 (red on origin/main: Rich inserted centering spaces before the braille-padded hero). Adapted from PR NousResearch#9880's test to the current banner internals.
…dependency not met" image_gen has several setup paths (FAL_KEY, managed Nous image generation, plugin providers) so it declares no single `requires_env`; doctor's generic branch then labelled a missing credential a "system dependency not met" and left it out of the "run hermes setup" summary. A small per-toolset setup-hint table: image_gen gets an actionable line pointing at `hermes tools`, counts toward the setup summary, and toolsets with a genuine system dependency (homeassistant) keep the old wording. Port of PR NousResearch#9548 by @skyc1e onto `hermes_cli/doctor_tools.py`. Fixes NousResearch#9516
Windows-footgun ratchet for the file touched by this fix (no behaviour change).
… key or SDK Review finding on NousResearch#109136: "no provider configured" was wrong when a provider IS selected but its SDK/key is absent. Word it as unavailable + where to look.
…on every surface
DEFAULT_CONFIG ships a root-level `personalities: {}` (from NousResearch#643) and the schema
whitelists it, but the single personality resolver read only
`agent.personalities`. A user who followed the generated config saw
"No personalities configured" from /personality on CLI, gateway and TUI.
`available_personalities()` now merges root `personalities` then
`agent.personalities` (later wins), so all three consumers pick both up.
Earlier attempt: PR NousResearch#9657 (@flobo3) patched the CLI loader only.
Fixes NousResearch#9636
Widens the new hook to the sibling interrupt surface: the TUI/desktop session.interrupt path stops a live turn exactly like the gateway's /stop, so plugins holding per-turn external resources get the same signal there (platform='tui'). Gated on a genuinely running turn; dispatch failures are swallowed so a plugin can never break the interrupt. Docs updated to describe both surfaces. Inspired by ChatGPT Work / Codex CLI 0.150.0 'Interrupt' hooks (hooks that run when an active top-level turn is interrupted).
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
૮ >ﻌ< ა ci reviewran on b32de7a — fix: close remaining sync CI regressions
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 042ce341d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4ed5a48767
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 531b14b47e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b32de7ac19
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Sync mrkillbob/hermes-agent main with NousResearch/hermes-agent main through upstream tip b6b53c6. This branch contains a two-parent merge from fork tip f41eb5e and upstream tip b6b53c6, preserving the fork's reviewed PR91 behavior at overlapping conflict points while bringing in all non-conflicting upstream commits. Focused validation: scripts/run_tests.sh on gateway lifecycle, multiplex MCP discovery, migration, scoped messaging, and MCP connection-key tests: 51 passed; git diff --cached --check: clean. The fork/upstream comparison before this PR was 786 fork-only commits and 1,055 upstream-only commits.