Commit graph

14 commits

Author SHA1 Message Date
kshitijk4poor
53bdef5775 test(cli): regression test for hermes update fork upstream sync (#26172)
Asserts that when hermes update runs on a fork whose local HEAD matches
origin/main but commit_count == 0, the early-return path still consults
_sync_with_upstream_if_needed() before printing "Already up to date!".

Locks in the fix from the parent commit so the upstream-sync call cannot
silently regress out of the commit_count == 0 branch.
2026-05-27 13:10:50 -07:00
emozilla
d5b73937db fix(cli): plug silent-divergence holes in --branch flag
Three follow-up fixes — all the same shape: silently doing the wrong
thing instead of either honoring --branch or refusing.

1) --check --branch <missing> raised CalledProcessError from
   'git rev-list ... --count' (check=True) when the branch didn't
   exist on origin. 'git fetch origin' succeeds without a refspec
   (it just fetches what's there), so the bad-branch case wasn't
   caught at the fetch step. Now verify the compare ref with
   'git rev-parse --verify --quiet' before rev-list and emit a
   friendly error.

2) _update_via_zip (Windows fallback for broken git file I/O)
   hard-coded branch = 'main', so on the ZIP path --branch=foo
   silently downloaded main.zip and told the user it worked. Refuse
   in that case instead — silently lying about which branch got
   installed is exactly what --branch was added to prevent.

3) _cmd_update_check PyPI path returned before looking at branch,
   so PyPI users running 'hermes update --check --branch=x' got a
   generic PyPI version check with no indication --branch was
   dropped. Now prints a one-line warning when --branch was explicit
   and non-main.

Also pull the '(getattr(args, branch, None) or main).strip() or main'
expression into _resolve_update_branch(args) — three callsites agree
on the same parsing.

Tests: 5 new tests for the --check + --branch matrix (named branch,
missing branch, default-main upstream-first, PyPI warning) and the
ZIP refusal. test_cmd_update.py is 20/20 green, broader hermes_cli/
suite (4952 tests) unchanged.
2026-05-21 02:14:08 -04:00
emozilla
51689a4206 feat(cli): add --branch flag to hermes update
`hermes update` has always hard-coded its target to `main`. Add --branch
so callers can update against a non-default channel while preserving every
existing behavior at the default:

- `hermes update`           still pulls main (no behavior change)
- `hermes update --branch X` pulls origin/X, auto-stashing and switching
                              local HEAD to X first if needed
- `hermes update --check --branch X` reports behindness against
                              origin/X (and skips the upstream/X probe,
                              since forks don't have upstream copies of
                              their own feature branches)
- Branch absent locally   → retry as `checkout -B X origin/X` (track)
- Branch absent everywhere → exit 1 with a clear error, after restoring
                              the user's prior stash so we don't strand
                              them in a weird state

The fork-upstream sync logic was already guarded on `branch == 'main'`,
so non-main updates correctly skip the upstream trampling without
further changes.

5 new tests cover: explicit --branch, default-to-main, switch-from-other,
track-from-origin, and the fail-cleanly case. Full test_cmd_update.py
suite (15 tests) passes on main.
2026-05-20 22:18:47 -04:00
kshitij
5fba236644
chore: ruff auto-fix PLR6201 resweep — tuple → set in membership tests (#27355)
Six days after #23937 (608 fixes) the codebase had accumulated 241 new
PLR6201 violations. Same mechanical `x in (...)` → `x in {...}` fix,
same zero-risk profile: set lookup is O(1) vs O(n) for tuple and the
two are semantically equivalent for hashable scalar membership tests.

All 241 instances fixed via `ruff check --select PLR6201 --fix
--unsafe-fixes`, zero remaining. Every changed value is a hashable
scalar (str/int/None/enum/signal); no risk of unhashable runtime
errors. No behavior change.

Test plan:
- 119 files changed, +244/-244 (net zero) — exactly one-line edits
- `ruff check` clean afterward
- Compile checks pass on the largest touched files (cli.py, run_agent.py,
  gateway/run.py, gateway/platforms/discord.py, model_tools.py)
- Subset broad test run on tests/gateway/ tests/hermes_cli/ tests/agent/
  tests/tools/: 18187 passed, 59 pre-existing failures (verified against
  origin/main with the same shape — identical failure count, identical
  category — all xdist test-order flakes unrelated to this change)

Follows the same template as PR #23937 ([tracker: #23972](https://github.com/NousResearch/hermes-agent/issues/23972)).
2026-05-17 02:29:41 -07:00
briandevans
c844d15c3d fix(update): stream npm install output so postinstall progress is visible (#18840)
`hermes update` ran the repo-root and ui-tui npm installs with both
`--silent` and `subprocess.run(..., capture_output=True)`, which hides
all output from optional postinstall scripts.  The largest of those —
`@askjo/camofox-browser`'s `npx camoufox-js fetch` — downloads a
Firefox-fork browser binary that can take many minutes on slow
connections.  Because nothing was printed during that wait, the updater
appeared to hang at "Updating Node.js dependencies..." and users
Ctrl-C'd, sometimes leaving `node_modules` partially installed.

Drop `--silent` and pass `capture_output=False` for the repo-root and
ui-tui paths so npm streams its `info run …` postinstall lines straight
to the terminal.  Output is still mirrored to `~/.hermes/logs/update.log`
by the existing `_UpdateOutputStream` wrapper, so SSH-disconnect safety
is preserved.

The `web/` install path is untouched — its build step is fast and does
not run binary-fetching postinstalls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 12:18:55 -07:00
adybag14-cyber
6d5d467d39 fix(update): use termux-all uv fallback path on Termux 2026-05-09 17:53:15 -07:00
adybag14-cyber
7c174e65f7 fix: harden termux update path with uv bootstrap and env guard 2026-05-08 16:49:37 -07:00
Steven Chou
9442a8fa22 fix(update): migrate config in non-interactive updates 2026-05-07 06:04:28 -07:00
briandevans
20edca75e9 fix(update): sync bundled skills to all profiles, including active (#16176)
`hermes update` iterated only non-active profiles when seeding bundled
skills. `seed_profile_skills()` uses a subprocess with an explicit
HERMES_HOME so it correctly targets any profile path; the `p.name !=
active` filter was the only thing preventing the active profile from
being included, leaving it silently on stale skill content after every
update.

Drop the filter and update the header line from "other profiles" to
"all profiles". The active profile is now seeded on the same path as
every other profile. The earlier `sync_skills()` call (module-level
HERMES_HOME) remains for backward compatibility; the subprocess-based
loop is reliable regardless of which HERMES_HOME the CLI was invoked
with.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 12:34:53 -07:00
brooklyn!
5f215b13ce
fix(docker): materialize bundled TUI Ink package (#16690)
* fix(docker): materialize bundled TUI Ink package

* fix(docker): keep nested deps out of build context

* fix(docker): make TUI Ink smoke check deterministic

* test(docker): skip dockerignore assertion in partial checkouts

* fix(docker): use lockfile install for vendored Ink deps

* test(cli): expect deterministic npm ci in /update flow

* fix(docker): fall back to npm install for vendored Ink deps

* fix(docker): keep bundled Ink source for TUI runtime builds

* fix(docker): dedupe React in vendored Ink package
2026-04-28 15:11:47 -05:00
Teknium
598cba62ad
test: update stale tests to match current code (#11963)
Seven test files were asserting against older function signatures and
behaviors. CI has been red on main because of accumulated test debt
from other PRs; this catches the tests up.

- tests/agent/test_subagent_progress.py: _build_child_progress_callback
  now takes (task_index, goal, parent_agent, task_count=1); update all
  call sites and rewrite tests that assumed the old 'batch-only' relay
  semantics (now relays per-tool AND flushes a summary at BATCH_SIZE).
  Renamed test_thinking_not_relayed_to_gateway → test_thinking_relayed_to_gateway
  since thinking IS now relayed as subagent.thinking.
- tests/tools/test_delegate.py: _build_child_agent now requires
  task_count; add task_count=1 to all 8 call sites.
- tests/cli/test_reasoning_command.py: AIAgent gained _stream_callback;
  stub it on the two test agent helpers that use spec=AIAgent / __new__.
- tests/hermes_cli/test_cmd_update.py: cmd_update now runs npm install
  in repo root + ui-tui/ + web/ and 'npm run build' in web/; assert
  all four subprocess calls in the expected order.
- tests/hermes_cli/test_model_validation.py: dissimilar unknown models
  now return accepted=False (previously True with warning); update
  both affected tests.
- tests/tools/test_registry.py: include feishu_doc_tool and
  feishu_drive_tool in the expected builtin tool set.
- tests/gateway/test_voice_command.py: missing-voice-deps message now
  suggests 'pip install PyNaCl' not 'hermes-agent[messaging]'.

411/411 pass locally across these 7 files.
2026-04-17 21:35:30 -07:00
Brooklyn Nicholson
a1d2a0c0fd feat: self update npm deps on hermes update 2026-04-11 18:29:18 -05:00
Teknium
9e411f7d70
fix(update): skip config migration prompts in non-interactive sessions (#3584)
hermes update hangs on input() when run from cron, scripts, or piped
contexts. Check both stdin and stdout isatty(), catch EOFError as a
fallback, and print guidance to run 'hermes config migrate' later.

Co-authored-by: phippsbot-byte <phippsbot-byte@users.noreply.github.com>
2026-03-28 14:26:32 -07:00
stoicneko
e1824ef8a6 fix(cli): fall back to main when current branch has no remote counterpart
`hermes update` crashed with CalledProcessError when run on a local-only
branch (e.g. fix/stoicneko) because `git rev-list HEAD..origin/{branch}`
fails when origin/{branch} doesn't exist. Now verifies the remote branch
exists first and falls back to origin/main.
2026-03-14 12:16:00 -07:00