Commit Graph
29 Commits
Author SHA1 Message Date
nesquena-hermesandwebtecnica a89808886f fix(commands): do not latch an empty skill-command cache after a failed load
loadSkillCommands() published readiness in a finally block that ran even when
/api/skills rejected, so one transient failure left
_skillCommandCacheReady=true with an empty cache. Because
ensureSkillCommandsLoadedForAutocomplete() only re-loads while
!_skillCommandCacheReady && !_skillCommandLoadPromise, no later picker pass ever
retried: skill commands stayed missing until a page reload even after the API
recovered.

Readiness is now set only after a successful current-generation commit; the
promise is cleared either way so the next pass can retry. The stale-generation
fence is unchanged (verified a reply from the outgoing profile still refuses to
commit).

This wedge is PRE-EXISTING on master (its finally sets ready unconditionally),
not introduced by this PR — fixed here because this change already reworks the
surrounding generation handling. Adds a reject-once/recover regression plus a
__failSkillsOnce() harness knob; reverting the fix turns it red.

Co-authored-by: webtecnica <webtecnica@users.noreply.github.com>
2026-09-18 02:39:35 +00:00
nesquena-hermes 4ba80ced12 changelog: AGENTS.md task-scoped pointers (#7593) + /api/models cache contract doc (#7560) 2026-09-17 23:01:06 +00:00
nesquena-hermesandwebtecnica 8861531dee docs(architecture): document the /api/models cache invalidation contract (#7560)
Records the shipped identity and invalidation contract for the /api/models
catalog cache in api/config.py — what is cached (in-memory snapshot, per-profile
models_cache.json, cold vs hot path), the three source axes and why each is
fingerprinted the way it is, and the one-directional deny-list invariant for the
volatile-key sets. Changes no runtime behavior; added after #7556 shipped, whose
review flagged the contract as undocumented.

Verified before merge: all 14 symbols the doc names exist in api/config.py
(_available_models_cache, _AVAILABLE_MODELS_CACHE_TTL, _get_models_cache_path,
_models_cache_provenance, _sync_models_cache_provenance,
_models_cache_source_fingerprint, _is_loadable_disk_cache,
_models_cache_file_fingerprint, _auth_store_semantic_fingerprint,
_AUTH_FINGERPRINT_VOLATILE_KEYS, _codex_models_cache_fingerprint,
_CODEX_CACHE_FINGERPRINT_VOLATILE_KEYS, _endpoint_advertised_model_ids), and the
cited test_unknown_codex_field_stays_in_fingerprint is real
(tests/test_issue7540_codex_catalog_fingerprint.py:287). docs/architecture/ is
allowlisted in .gitignore with both the dir and /** lines, so the new file is
genuinely trackable.

Co-authored-by: webtecnica <webtecnica@users.noreply.github.com>
2026-09-17 23:00:04 +00:00
nesquena-hermesandsteveafrost e07606a6b2 docs(agents): scope documentation pointers by task and state completion criteria (#7593)
Restructures AGENTS.md so contributors read the references that match their
change instead of a blanket four-file reading list, and states explicit
completion/verification criteria in place of the compressed ten-rule summary.

Verified before merge: all 12 referenced paths exist on master (README,
CONTRIBUTING, docs/CONTRACTS.md, docs/GUIDELINES.md, CHANGELOG, ARCHITECTURE,
TESTING, docs/onboarding.md, docs/troubleshooting.md, docs/rfcs/README.md,
docs/UIUX-GUIDE.md, DESIGN.md), the referenced ./scripts/test.sh exists, and
the ten rules removed from AGENTS.md are all preserved in docs/GUIDELINES.md —
which the new version still points to. Net -2 lines, so no information is lost.

Co-authored-by: steveafrost <steveafrost@users.noreply.github.com>
2026-09-17 22:59:52 +00:00
nesquena-hermes 16ebfcace8 changelog: zip media delivery (#7612) + Agent moved-name resolution (#7574) 2026-09-17 21:58:48 +00:00
nesquena-hermesandmikemchargue 818c392ed4 fix: resolve Hermes Agent names moved by the Sep 2026 decomposition (#7574)
The Agent's September 2026 decomposition moved several names the WebUI uses into
sibling modules. The old import paths resolved only through PEP 562 __getattr__
compat pointers whose removal date (2026-09-14) has already passed. Every affected
WebUI call site is wrapped in a broad except, so once those pointers go away nothing
crashes -- features silently degrade: MCP tools vanish from turns, the per-turn
approval session key never binds, Claude Code credential linking stops, and the
kanban bridge raises AttributeError.

Adds api/agent_compat.py::agent_attr(owner, name, home, default), which resolves a
moved name via the original module's own namespace (pre-split Agents and test stubs),
then the new home module (split Agents, with or without the pointers), then plain
attribute access -- and routes the 8 affected call sites through it.

Gate: Codex SAFE TO SHIP. All 12 mappings verified against the installed Agent's
authoritative compat_manifest.json; owner-wins precedence is correct because PEP 562
pointers do not populate vars(owner), so current pointers are bypassed without
warnings; the only explicit defaults are the pre-existing optional kanban fallbacks
and remain semantically equivalent; turn-approval identity, MCP discovery/reload/status,
OAuth credential reading, LM Studio probing, and all three kanban paths preserve their
previous values and control flow; cached import_module costs ~1.36us and the hottest
site is a 0.3s kanban poll, not per-token streaming (caching the callable would break
supported module replacement/monkeypatching). Tests are non-vacuous across pre-split,
pointer-present, and pointer-removed shapes. Full suite 15,597 pass with only the known
box-baseline singleton. Maintainer proof: agent_attr resolves the moved name with zero
HermesPluginCompatWarning while a clean-master control still resolves via the pointer
and warns.

Co-authored-by: mikemchargue <mikemchargue@users.noreply.github.com>
2026-09-17 21:57:25 +00:00
nesquena-hermesandcarlotestor 8e100d0540 fix(media): serve .zip archives through /api/media (#7612)
Archives resolved to application/octet-stream (.zip absent from MIME_MAP) and were
therefore rejected by the session MEDIA: token allow-list, so a MEDIA:/path/file.zip
link always failed to open. Adds .zip -> application/zip and admits archives to the
session-token type set. Archives are download-only by construction: _ARCHIVE_TYPES is
never added to the inline-preview sets, so they always get Content-Disposition:
attachment.

Gate: Codex SAFE TO SHIP (disposition verified incl. inline=1 and uppercase .ZIP;
confinement requires exact canonical path equality vs a non-user MEDIA: token; the
#3234 state/secret deny guard runs before the allow decision and reproduced a 403 on a
token-authorized backups/state-backup.zip; traversal and workspace-symlink both 403;
.docx/.xlsx mappings intact). Full suite 15,580 pass with only the known box-baseline
singleton. Maintainer added a live behavioral proof (the PR's own tests are source-string
assertions only); it failed on clean master and passed on this head.

Co-authored-by: carlotestor <carlotestor@users.noreply.github.com>
2026-09-17 21:40:23 +00:00
nesquena-hermes 0efa75827a fix(streaming): pass config overrides into context-length fallback (#1896)
The two get_model_context_length() fallback callsites in api/streaming.py
(session save + SSE usage payload) were calling the resolver with only
model + base_url. When the agent's compressor reports 0 (fresh/cached/
transitioning agent), resolution fell through to the 256K DEFAULT_FALLBACK
even when users had set model.context_length: 1048576 in config.yaml.

For LCM users on 1M-context models, the wrong window cascaded into a
session-killing failure: auto-compression triggered at ~25% of the wrong
value, floods of compress requests, 429s, credential pool exhaustion,
fallback 429s, then 'API call failed after 3 retries'.

Reported by @AvidFuturist on Discord with deepseek-v4-flash. Reproduced 5x.

Both callsites now pass config_context_length, provider, and
custom_providers. The resolver consults these BEFORE probing, so the
config override wins. Both are wrapped in except TypeError blocks that
retry with the legacy 2-arg form for older hermes-agent builds whose
get_model_context_length signature pre-dates these kwargs.

Tests: 7 source-string regressions guarding both call shapes, the safe
config parse, the legacy fallback, and the per-profile config source.
Also bumped the line-distance assertion in test_pr1341 (the test
explicitly invites bumping when a new pre-save mutation block is added).

Closes #1896

Co-authored-by: Hermes Agent <agent@hermes.local>
2026-05-08 16:08:42 +00:00
nesquena-hermes f456daa574 fix(streaming): include profile home in agent cache signature (#1897)
Same-session profile switches reused cached AIAgent from previous profile,
silently leaking the old persona's SOUL.md / system prompt into the new
profile's turns. session_id stays stable across profile switches, and the
signature didn't include the active profile home, so every signature input
matched and the stale agent was returned from SESSION_AGENT_CACHE.

Append _profile_home to the signature blob so profile switches force a
cache miss and a fresh agent build under the new HERMES_HOME (which
triggers a fresh load_soul_md() call).

Tests: 3 source-string regressions guarding the signature contract,
ordering, and empty-home fallback.

Closes #1897

Co-authored-by: Hermes Agent <agent@hermes.local>
2026-05-08 16:08:18 +00:00
Hermes Agent 4f50cb2511 Reference correct issue number (#1431) in comment + CHANGELOG 2026-05-01 23:47:46 +00:00
Hermes Agent 4adbb5ebee Hide composer-footer toolsets chip (cramped layout)
The session-toolsets restriction chip (#493) was making the composer
footer too cramped on narrower widths once it was sharing space with
model, reasoning effort, profile, and context-usage indicators.

Surgical fix: `_applyToolsetsChip()` now sets the wrap to display:none
unconditionally. Underlying state and the /api/session/toolsets endpoint
still work, so any cron job or scripted client that relies on
`enabled_toolsets` continues unaffected. To be revisited when the
footer layout is redesigned (#1430).
2026-05-01 23:47:13 +00:00
Hermes Agent 2a0757fb46 v0.50.253: CHANGELOG entry for the batch (#1342 + #1388 + #1381 + 2 Opus follow-ups) 2026-05-01 06:54:30 +00:00
Hermes Agent 67193faf38 Apply Opus pre-release follow-ups for v0.50.253
Three small fixes from Opus review of the merged stage diff:

1. Strip 9 orphan wiki_* i18n keys (72 lines) from PR #1342 — leaked
   from a different branch, zero references outside i18n.js.

2. /branch endpoint: reject non-string session_id with explicit 400
   (was raising TypeError → generic 500 from get_session()).

3. /branch endpoint: reject negative keep_count with explicit 400
   (Python slice semantics on negative produces 'all but last N',
   confusing fork behavior).

Plus tests/test_v050253_opus_followups.py — 3 regression tests pinning
all three fixes.

Verified: 3558 pytest passing.
2026-05-01 06:53:32 +00:00
Hermes Agent 8cd3680c0c Absorb starship-s commit cddd175: tighten composer spacing on 320px legacy phones
Pulls in the extra commit pushed to PR #1381 after our initial absorb. Adds a
@media (max-width: 340px) block that compacts gutters (composer-wrap padding,
composer-footer gap, composer-left gap) without shrinking the 44px touch
targets. Plus its regression test.

Verified with apply --check failed but actual apply succeeded — the failure
was due to context drift from our earlier CSS specificity fix; the new lines
landed at the correct location. test_mobile_layout.py: 47 tests passing.
2026-05-01 06:15:13 +00:00
Hermes Agent 1c356bf321 PR #1381 fix: prevent mobile-config-btn from leaking into desktop view (CSS specificity)
The .composer-mobile-config-btn{display:none} base rule was at line 896 but
.icon-btn{display:flex} (the button's other class) was at line 941 — equal
specificity, but later in source wins. Result: the button was visible at
desktop widths, sandwiched between the workspace and model chips.

Bumping the base rule's selector to .icon-btn.composer-mobile-config-btn
gives it specificity 0,0,2,0 (vs .icon-btn at 0,0,1,0), so it always wins
the cascade. The two narrow-viewport rules already use !important and remain
unaffected — desktop hides cleanly, mobile shows correctly.

Verified via Agent Browser CDP: 1440x900 desktop now shows the standard
chips only (no extra config button); iPhone 14 mobile shows the new compact
config btn at 44x44 with the panel toggling correctly. Screenshots:
/tmp/may2-shots/desktop-final.png, mobile-{closed,open}-final.png
2026-05-01 05:49:30 +00:00
Hermes Agent 1a76e8761e Mobile composer layout: progressive-disclosure config panel + scoped titlebar safe-area (#1381) 2026-05-01 05:36:59 +00:00
Hermes Agent 18d960eb7a Revert PR #1342's test_issue1195 rewrite — del sys.modules corrupts shared module state
PR #1342's rewrite introduced `del sys.modules['api.config']`, 'api.profiles']`
anti-pattern that breaks tests/test_live_models_ttl_cache.py::test_live_models_cache_is_profile_scoped
(v0.50.252) when run after test_issue1195_*. The pattern is explicitly banned per
~/WebUI/docs/agent-memory/pytest-isolation.md — sibling tests that import api.profiles
later see the wrong (re-imported) module.

Master's version of this test passes 5/5 and uses no del sys.modules calls. The PR's
core /branch feature does NOT depend on this test rewrite — reverting it loses no
coverage of the branching feature.
2026-05-01 05:35:24 +00:00
Hermes Agent 52bfceaa3b Add /branch command to fork conversations from any message (#1342, fixes #465)
Fix: gate parent_session_id emission in compact() on truthiness so
sessions without a fork link don't leak parent_session_id: None and
break the v0.50.251 lineage end_reason gating in agent_sessions.py.
The /branch endpoint sets the field on saved forks; everything else
keeps the v0.50.251 sidebar lineage path as the canonical source.
2026-05-01 05:32:45 +00:00
Hermes Agent fea47bd986 Heal 'provider: local' mid-conversation crash for local-model users (#1388, fixes #1384) 2026-05-01 05:29:42 +00:00
Hermes Agent afc68d3a13 CHANGELOG: document Opus pre-release follow-ups for v0.50.252 2026-05-01 05:07:25 +00:00
Hermes Agent fc8898161e Apply Opus pre-release follow-ups (force redaction, log profile fallback) 2026-05-01 05:07:09 +00:00
Hermes Agent 6572f81abb Add v0.50.252 changelog entry (6 contributor PRs) 2026-05-01 05:04:15 +00:00
Hermes Agent 2bc6f9a997 Add regression test for #1386 (model='unknown' init guard) 2026-05-01 04:48:24 +00:00
Hermes Agent e36def33cd Show profile home in /status command (refs #463) (#1380) 2026-05-01 04:46:37 +00:00
Hermes Agent 5c5ca7d2ef Intercept CLI-only slash commands in WebUI (#1382) 2026-05-01 04:46:30 +00:00
Hermes Agent 838b931047 Keep API credential fallback redaction active (#1379) 2026-05-01 04:46:17 +00:00
Hermes Agent a6d831fc63 Cache /api/models/live with 60s TTL (#1378) 2026-05-01 04:46:15 +00:00
Hermes Agent d21c97205e Harden streaming scroll unpin behavior (#1360) (#1377) 2026-05-01 04:46:12 +00:00
Hermes Agent d1e1c4eeec Fix CLI session import fallback model default (#1386) 2026-05-01 04:46:10 +00:00