Commit graph

1589 commits

Author SHA1 Message Date
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
kshitij
2b6897f982
fix(computer-use): target Linux app windows reliably (#63725)
* fix(computer-use): target Linux app windows reliably

Resolve app filters through the canonical cua-driver MCP app metadata and join running app PIDs back to windows. Preserve an exact selected window across capture_after, support direct capture by pid/window_id, and send the active window ID for coordinate pointer actions on Linux.

Co-authored-by: annguyenNous <annguyenNous@users.noreply.github.com>
Co-authored-by: grimmjoww578 <willies578@gmail.com>
Co-authored-by: ai-ag2026 <261867348+ai-ag2026@users.noreply.github.com>

* fix(computer-use): address review on PR #63725

Address three review comments from @f-trycua:

1. type_text, press_key, and hotkey now carry _active_window_id and
   fail closed when it is missing. Previously they sent only the PID,
   so CUA Driver fell back to the first window for that PID — input
   could reach the wrong window in multi-window apps.

2. Coordinate scroll x/y are now capability-gated behind
   input.scroll.coordinates. CUA Driver 0.7.1 Linux schema rejects
   x/y on scroll; omitting them when the driver doesn't advertise
   support avoids the schema rejection while still routing via
   window_id.

3. Windows are sorted by z_index descending (higher = front, per CUA
   Driver semantics) instead of ascending. Null z_index (Wayland) is
   coerced to 0 in _ingest_windows so it doesn't crash the sort and
   sorts to the back instead of being selected as the capture target.

---------

Co-authored-by: LeonSGP43 <cine.dreamer.one@gmail.com>
Co-authored-by: annguyenNous <annguyenNous@users.noreply.github.com>
Co-authored-by: grimmjoww578 <willies578@gmail.com>
Co-authored-by: ai-ag2026 <261867348+ai-ag2026@users.noreply.github.com>
2026-07-16 00:34:20 +05:30
Teknium
6020b9f4fe chore: AUTHOR_MAP entry for JiaDe-Wu (PR #34742 salvage) 2026-07-15 09:59:38 -07:00
Teknium
f8630a1456 chore: add Burgunthy to AUTHOR_MAP (PR #20096 salvage) 2026-07-15 09:50:05 -07:00
Teknium
306e2d2318 chore: AUTHOR_MAP entry for Epoxidex (PR #29820 salvage)
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 / JS & TS checks (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-15 06:38:28 -07:00
Teknium
a7ef17da7a chore(release): map dorokuma in AUTHOR_MAP 2026-07-15 06:25:10 -07:00
Teknium
2fc0e3d1aa fix(codex): guard the continuation nudge against role-alternation violations
Follow-up to the salvaged #63690: when the interim assistant message is
too empty to append (no content and no reasoning of any kind), the last
message in history is still the prior user/tool turn — appending the
user-role nudge there would create a user→user or tool→user sequence
that strict providers reject. Only append the nudge when the last
message is an assistant turn. Also add IpastorSan to AUTHOR_MAP.
2026-07-15 00:13:24 -07:00
Teknium
b34e565957 feat(models): catalog-labeled silent default — GLM-5.2 marked "default": true in the model catalog
The remote model catalog (website/static/api/model-catalog.json) now labels
exactly one entry per provider block with "default": true — z-ai/glm-5.2 for
both OpenRouter and Nous Portal. That labeled entry is the model Hermes
silently lands on when the user never picked one, and it can be rotated by
editing the manifest alone: no release needed.

- model_catalog.py: get_default_model_from_cache() reads the label from the
  in-process/disk cache only — never triggers a network fetch, so hot
  resolution paths (agent build, gateway session setup) stay network-free.
- models.py: get_preferred_silent_default_model() resolves catalog label
  first, PREFERRED_SILENT_DEFAULT_MODEL constant second (offline/fresh
  install). _PROVIDER_SILENT_DEFAULT_OVERRIDES dict replaced by
  _SILENT_DEFAULT_PROVIDERS routing through the shared resolver.
  fetch_openrouter_models() preserves the "default" badge through live
  /v1/models refreshes so the picker shows it.
- scripts/build_model_catalog.py: generator emits the default label so
  regeneration can't drop it.
- website/docs/reference/model-catalog.md: schema documents the new field.
- Salvaged from PR #61141 (@HumphreySun98): bare-provider /model switches
  (/model nous) route through the cost-safe default instead of curated
  entry [0].
- tests: catalog-label precedence, constant fallback, stale-label fallback,
  cache-only (no network) guarantee, and a shipped-manifest contract test
  pinning the labeled entry to PREFERRED_SILENT_DEFAULT_MODEL.

E2E (temp HERMES_HOME): fresh-install constant fallback, shipped-manifest
label read, release-free rotation (relabeled cache -> new default across
models.py, tui_gateway, and gateway empty-model paths) all verified.
2026-07-15 00:10:31 -07:00
Teknium
d6c14a952f chore(release): map liuwei666888 in AUTHOR_MAP 2026-07-15 00:10:22 -07:00
kshitijk4poor
d2c81eb681 chore(release): map pixel4039 in AUTHOR_MAP (PR #64420 salvage) 2026-07-15 10:58:36 +05:30
Teknium
e357b69a61 chore(release): map KCAYAAI in AUTHOR_MAP 2026-07-14 21:31:32 -07:00
Teknium
7df595c58b chore: AUTHOR_MAP entry for webtecnica (PR #63360 salvage) 2026-07-14 21:31:04 -07:00
Teknium
5d410355ac chore(release): map justinschille in AUTHOR_MAP 2026-07-14 21:08:22 -07:00
kshitijk4poor
4554fe128a fix(slack): complete agent view workspace routing 2026-07-14 13:58:36 -07:00
kshitijk4poor
0d01831919 chore: add changhyun.min@gmail.com to AUTHOR_MAP (minchang, PR #42231) 2026-07-15 00:09:24 +05:30
Teknium
46e87b14fd chore(release): map unsupportedpastels in AUTHOR_MAP
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 / JS & TS checks (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-14 07:02:05 -07:00
Teknium
72ac0d6af0 chore: add neo-claw-bot to AUTHOR_MAP (PR #58465 salvage) 2026-07-14 06:49:36 -07:00
kshitijk4poor
444b5e96fa chore(release): map arnispiekus in AUTHOR_MAP
For PR #63581 salvage (telegram: require getUpdates progress before
polling is healthy).
2026-07-14 17:46:21 +05:30
kshitijk4poor
c5aaf76468 chore(release): map @Roseyco-management in AUTHOR_MAP
For PR #63581 salvage (telegram: require getUpdates progress before
polling is healthy). SilentKnight87 uses a noreply GitHub email which
auto-skips.
2026-07-14 17:32:41 +05:30
Vishal Dharmadhikari
b8eb89f5c9 feat(gemini): improve request context for support and compatibility
Include the Hermes client name and version with Gemini inference, model and tier checks, and TTS requests. Add focused coverage for the request headers and keep the Gemini-specific context scoped to Google Gemini endpoints.
2026-07-13 22:26:19 -07:00
kshitijk4poor
2ccfdb2db4 fix(agent): exempt parseable vLLM/LM Studio output-cap errors from compression-disabled guard
Salvage of #63862. is_output_cap_error() returns False for vLLM/LM Studio
error messages that contain 'prompt contains ... input tokens' (treated as
input-overflow signal). But parse_available_output_tokens_from_error() CAN
extract a valid available_tokens from those same messages. The
compression-disabled guard only checked is_output_cap_error(), so vLLM/LM
Studio users with compression off still got a terminal failure instead of
the max-tokens retry.

Fix: also exempt when parse_available_output_tokens_from_error() returns a
value — that function determines whether the retry path can actually handle
the error, so it's the right predicate for the exemption.

Added test: verify vLLM-format error with compression_disabled=False still
triggers the max-tokens retry path.

Co-authored-by: dmabry <dmabry@users.noreply.github.com>
2026-07-14 03:58:54 +05:30
ethernet
29b8cacfab fix(ci): add missing Δ Wait column to skipped job rows 2026-07-13 17:46:11 -04:00
ethernet
e117478eb3 fix(ci): align baseline gantt bars to current job start
Baseline bars were positioned at their absolute timeline offset, which
included the baseline run's own wait time — making duration comparisons
hard since the bars were visually offset. Now each baseline bar starts
at the same left position as its corresponding current job, so the two
bars directly overlap for at-a-glance duration comparison.

Also removed the now-unused bl_t0 / bl_max / bl_jobs_timed variables
that tracked the baseline timeline position.
2026-07-13 17:46:11 -04:00
ethernet
f0b7cf3836 feat(ci): show per-job wait times in timing report
Add wait time computation: for each job, wait_s = started_at - max(completed_at
of all jobs that finished before it started). This is a timestamp heuristic
(no workflow YAML dependency parse needed) that's accurate for pipeline-shaped
CI where the critical path is linear at each stage.

Shows up in:
- Job table: new Wait + Δ Wait columns
- Gantt chart: hatched bar segment before the run bar
- Step details: '(wait Xs)' annotation in the summary line
- Markdown summary: Total wait row with delta vs baseline
- Stats: total_wait / bl_total_wait in compute_stats

Also completes the skipped-jobs UI:
- Skipped stat card in stats cards
- Skipped row in markdown summary table

Backward compatible: old cached baselines without wait_s annotate on load.
2026-07-13 17:46:11 -04:00
ethernet
7beca22bc0 fix(ci): exclude skipped jobs from timing deltas and stats
Skipped jobs (conclusion == 'skipped') have null/zero-duration timestamps
that polluted every downstream computation: they counted as 'unchanged'
(0 vs 0) in faster/slower tallies, showed meaningless '0.0s (0%)' deltas
in the job table, rendered phantom gantt bars, and inflated wall/compute
totals.

Add is_skipped() helper and apply it consistently:
- compute_stats: exclude from wall/compute + faster/slower/unchanged;
  add 'skipped' and 'bl_skipped' counts
- _gantt_bars: filter from current bars, baseline bars, and axis calc
- _job_table: show 'skipped' label instead of durations/deltas
- _step_details: skip entirely (no meaningful step data)
- _regressions: exclude from both current and baseline sides
2026-07-13 17:46:11 -04:00
kshitijk4poor
2fc3f9c1ff fix(deepinfra): harden multimodal provider routing
Prevent credential forwarding across catalog redirects, retain explicit opt-in semantics for paid media backends, fail closed on invalid provider configuration, avoid mixed-catalog and output-limit assumptions, and reserve native STT provider names.
2026-07-14 02:59:39 +05:30
ethernet
7fe1cb384e feat(ci): python test speedups 2026-07-13 15:29:20 -04:00
kshitijk4poor
2627933f33 fix(agent): distinguish missing from broken compression locks 2026-07-14 00:14:55 +05:30
kshitijk4poor
0512f06a6a fix(auth): centralize pool auth normalization
Normalize Anthropic setup-token metadata for every PooledCredential construction path, persist corrected manual entries, heal legacy rows on load without copying global fallback credentials into profiles, and map the contributor email for release attribution.
2026-07-13 23:20:48 +05:30
teknium1
d2b2be0f01 chore(release): map delegation contributor 2026-07-13 07:28:21 -07:00
Teknium
d921005e25 chore(release): map @kavioavio in AUTHOR_MAP 2026-07-13 04:31:55 -07:00
Teknium
f813c7ddad chore(release): map @Tortugasaur desktop commits 2026-07-13 03:00:43 -07:00
Teknium
0709714a6c chore(release): map @yinkev in AUTHOR_MAP 2026-07-12 23:09:41 -07:00
Teknium
acb3bde097 chore(release): map @jakelongvu-bot in AUTHOR_MAP 2026-07-12 22:43:57 -07:00
Jeffrey Quesnelle
6d3009454d
Merge branch 'main' into bb/salvage-43809-wsl-bridge 2026-07-12 22:46:49 -04:00
Teknium
7c19eb80a8 docs(dashboard): align approval mode guidance 2026-07-12 17:42:42 -07:00
teknium1
68107ae9d0 chore(release): map @ansel-f in AUTHOR_MAP 2026-07-12 04:32:52 -07:00
Brooklyn Nicholson
650d04d879 chore(attribution): map VrtxOmega@pm.me -> VrtxOmega (#43809 salvage) 2026-07-12 05:32:54 -04:00
Brooklyn Nicholson
33ab65a14f chore(attribution): map palmer@dugoutfantasy.com -> professorpalmer (#48591 salvage) 2026-07-12 05:08:13 -04:00
Brooklyn Nicholson
e0a650fa7d refactor(desktop): text-only workspace status menu + attribution
Align the workspace status-bar dropdown with the rest of the status bar: drop
the per-item icons (they mixed lucide size-4 with a Codicon 1rem glyph and were
the only status-bar menu carrying item icons), leaving text-only items on the
shared DropdownMenuItem primitive with default typography. The status-bar
trigger keeps its FolderOpen glyph, consistent with sibling items.

Also map true@supersynergy.de → Supersynergy in AUTHOR_MAP.
2026-07-12 04:56:24 -04:00
Brooklyn Nicholson
f63535a347 chore(attribution): map esthon@gmail.com → esthonjr (#61950 salvage) 2026-07-12 04:45:56 -04:00
kshitijk4poor
37a942650f fix(gateway): scope context refs to runtime profile 2026-07-11 23:46:13 +05:30
kshitijk4poor
a46bb90d6b chore: map PR #62125 contributor 2026-07-11 22:59:49 +05:30
teknium1
c552984534 chore: map usage attribution contributors
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-11 05:59:42 -07:00
teknium1
31152ae108 fix(providers): align Fireworks integration with project policy 2026-07-11 05:43:35 -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