Commit Graph
388 Commits
Author SHA1 Message Date
carlotestor 05aae134cf Merge branch 'master' into feat/gateway-run-reattach-after-restart 2026-09-24 15:51:42 +01:00
nesquena-hermes c2c8ef5fce Merge PR #7301 from laitekin/fix/7299-hidden-session-poll 2026-09-24 11:26:41 +00:00
nesquena-hermes 0adc1f6e4f Merge PR #7754 from starship-s/fix/image-turn-display-context 2026-09-24 10:54:56 +00:00
latekin 08dbd87a36 Merge branch 'master' into fix/7299-hidden-session-poll 2026-09-24 18:20:37 +08:00
starship-s 089fb57d25 fix(chat): honor edit watermarks for distinct image rows
Apply the existing truncation and checkpoint-order eligibility to marked
state.db image rows before insertion. Keep removed turns out of full,
limited, and model-context reads without changing no-watermark replay.
Preserve conflicting provider payloads for a uniquely proven retained
image row across Undo without restoring distinct removed rows.

Assisted-by: Hermes Agent:gpt-6-sol
Assisted-by: Codex:gpt-6-luna
2026-09-24 03:04:50 -06:00
tancouandClaude Fable 5.1 dbf0179c53 fix(mcp): report runtime_scope on /api/notes/sources and surface it in the Notes drawer
Review follow-up on #7720 (Greptile P2): the external Notes drawer reads the
same profile-bound MCP inventory as the MCP panel but dropped the
``runtime_scope`` label, so a profile whose runtime scope could not be
confirmed rendered its note sources as inactive/configured with no
explanation. ``/api/notes/sources`` now returns ``runtime_scope`` and the
drawer shows the existing ``mcp_runtime_scope_unavailable`` notice (same key,
no new locale strings) when it is ``unavailable``.

Tests: the skewed-routing unit test now also asserts the notes response
carries ``runtime_scope: "unavailable"`` with its sources inactive.
docs/troubleshooting.md mentions the drawer next to the panel.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 09:53:02 +02:00
tancouandClaude Opus 5 90b814f673 fix(mcp): scope MCP status, inventory and /reload-mcp to the request profile
Two profiles configuring a same-named MCP server shared one connection and
the MCP settings panel showed another profile's runtime ("Active, N tools"
next to an empty inventory); /reload-mcp stopped every profile's servers and
rediscovered from the process-default config.

- api.profiles._set_hermes_home() is the single writer of the process-profile
  home: it records get_process_profile_home() and hands it to Hermes Agent's
  hermes_constants.pin_process_hermes_home when available, at startup and on
  switch_profile(process_wide=True), so the per-turn HERMES_HOME mirror no
  longer makes every turn look like the process profile (bare-name,
  cross-profile MCP keys) and the anchor cannot drift from HERMES_HOME.
- Run get_mcp_status/registry reads and /reload-mcp inside
  api.mcp_runtime.mcp_runtime_scope(): request profile's Hermes-home override
  and secret scope (root included), no os.environ mutation, restored on exit.
- One ledger predicate, ledger_key_serves_view() (owned via
  _server_scope_keys/key scope, or adopted via _server_tool_scopes), is shared
  by status, inventory and the reload summary. The Agent's launch-profile view
  is process-wide and name-indexed, so filter_runtime_status_to_view()
  rebuilds connected/tools/status/error from the entries serving the profile:
  the root profile never shows a routed profile's connection (nor lets its own
  parked failed-spawn task borrow a routed profile's live same-named one).
- Inventory lists only tools in the profile's own registry slot for servers it
  configures; responses carry runtime_scope.
- Fail closed when the agent's routing does not match the resolved profile:
  hide runtime data (runtime_scope "unavailable", shown as a notice in the MCP
  panel, 14 locales) and refuse /reload-mcp.
- /reload-mcp shuts down only the profile's own ledger names (parked
  included), drops its own connect cooldown/error entries so a failed spawn is
  retried (the wildcard cleared every cooldown; a scoped shutdown only clears
  the live keys it tears down), rediscovers under the profile's home and
  counts live connections only. The bare wildcard remains for agents without
  profile-scoped MCP.
- Signature introspection is centralized (accepts_keywords) and falls back to
  the bare call instead of blanking every status; ledger key helpers resolve
  to the Agent's tools.mcp_tool_scope when present; tools.mcp_tool is
  resolved by full name so stubbed agents still work.
- ARCHITECTURE.md §4.10 and docs/troubleshooting.md document the boundary.
- Tests: agent-free contract (models adoption, parked tasks, cooldowns and the
  process-wide root view) and real-Agent integration (fake stdio MCP server,
  skips without hermes-agent + mcp SDK).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 09:53:02 +02:00
starship-s 5d42c2acd2 chore(chat): merge upstream for image-turn PR
Keep image-turn context tagging and upstream's typed steer-wrapper cleanup
in the same settlement path. Verify the combined recovery and streaming
behavior against current master.

Assisted-by: Hermes Agent:gpt-6-sol
2026-09-23 18:43:39 -06:00
starship-s c101b54c02 fix(chat): preserve journal recovery after a dead image turn
Count a proved WebUI-owned pending row in the display baseline before
accepting a state.db self-heal. Without assistant output past that turn,
leave pending state for the run journal to restore partial text and the
interruption marker instead of clearing it prematurely.

Assisted-by: Hermes Agent:gpt-6-sol
Assisted-by: Codex:gpt-6-luna
Assisted-by: Claude Code:claude-opus-5-5
2026-09-23 15:06:58 -06:00
starship-s d07c60a92a fix(chat): preserve submitted image turns on stale recovery
When a dead stream is reconciled from state.db, retain the submitted
prompt and attachment in the sidecar while keeping the Agent-enriched
row in model context. Use one parent snapshot for full-session conflict
projection so the sidecar owner is stable across the display merge.

Assisted-by: Hermes Agent:gpt-6-sol
Assisted-by: Codex:gpt-6-luna
Assisted-by: Claude Code:claude-opus-5-5
2026-09-23 14:39:11 -06:00
carlotestor 5d590bdc7f refactor: shrink gateway reattach diff without behaviour change
Inline endpoint resolution, fold HTTP error branches, merge duplicate
tests into parametrized cases, trim comments and docstrings.
2026-09-23 19:12:46 +00:00
starship-s 0be6a1f454 fix(chat): prevent duplicate bubbles for conflicting provider payloads
Record pending-turn proof under caller-owned session locks during normal
runs and credential recovery. Preserve both conflicting provider payloads
for replay, but display one sidecar-owned bubble when row identity and
visible content are unambiguous.

Assisted-by: Hermes Agent:gpt-6-sol
Assisted-by: Codex:gpt-6-luna
2026-09-23 12:56:46 -06:00
nesquena-hermes ab130f2cd0 Merge PR #7610 into stage/7610-oob-writeback 2026-09-23 18:23:35 +00:00
starship-s 63c8e3df31 fix(chat): keep pending image turns private through reload
Persist trusted pending Agent timestamp evidence before the model call so
session reads, including metadata polls and cold reloads, keep only the
submitted prompt and attachment visible. Preserve conflicting provider
payloads without guessing which copy is newer.

Assisted-by: Hermes Agent:gpt-6-sol
Assisted-by: Codex:gpt-6-luna
2026-09-23 11:34:30 -06:00
carlotestor 7ba246bfc0 fix(gateway): reattach runs-API turns after a WebUI restart instead of marking them interrupted
A gateway-backed turn on the runs API executes in the Hermes Gateway, but the
run id only lived in process memory, so a WebUI restart orphaned the turn and
stale-pending repair appended 'Response interrupted' while the run finished
on the gateway.

- persist session.gateway_run {run_id, stream_id} as soon as POST /v1/runs returns
- send Idempotency-Key webui-<stream_id> so the gateway keeps a durable run record
- on startup (after bind, before serving) re-register the stream and follow
  GET /v1/runs/{id} until terminal; write back the real output, surface a
  parked approval once, keep Stop working, clear the record on every settlement
2026-09-23 16:30:21 +00:00
webtecnica 618325501e Merge upstream/master into fix/oob-marker-writeback 2026-09-23 11:19:34 -03:00
webtecnica 6d1753bb6c fix(streaming): extract inner steer text from typed steer rows in place (#7600) 2026-09-23 11:19:25 -03:00
nesquena-hermes 9b6f70c959 Merge PR #7767 into stage/7767-runtime-model 2026-09-23 14:11:17 +00:00
nesquena-hermes c5d8e5fe4f Merge master into stage/7761-watcher-fence
# Conflicts:
#	CHANGELOG.md
2026-09-23 12:47:36 +00:00
Anthony Ruiz c45cab3779 feat(streaming): publish observed local runtime model to SSE and journal 2026-09-23 11:11:52 +00:00
nesquena-hermes dc554cbd1c Merge PR #7165 into stage/7165-custom-allowlist 2026-09-23 10:22:41 +00:00
Anthony Ruiz 986e0fdd85 fix(gateway-watcher): fence stale projections after final subscriber removal 2026-09-23 10:00:57 +00:00
happy5318andClaude Opus 4.8 0fcd584274 fix(models): dict-shaped models is per-model metadata, not an allowlist (re-gate 9/23)
Re-review #7165 (nesquena-hermes 2026-09-23T06:21:57Z, CHANGES_REQUESTED).

CORE: a dict-shaped custom_providers[].models mapping (what Hermes Agent's
setup flow writes, e.g. {chat-a: {context_length: 128000}}) was treated as an
allowlist by iterating its keys, collapsing the live /v1/models catalog to a
single saved default while the CLI live-probed the full list. The Agent defines
exactly this contract in hermes_cli/model_switch.py::_models_config_is_allowlist:
a mapping is per-model metadata, NOT a catalog narrow.

Fix (all 3 spec points):

1. api/routes.py::_custom_provider_allowlist_ids: added
   _custom_provider_models_discover_is_false(_cp) (mirrors
   api.config._provider_discover_allowed / Agent
   model_switch_providers.py:557: bool False or string false/no/0,
   case-insensitive). In the dict branch, when discovery is NOT explicitly
   false, return no allowlist so the live probe returns the full catalog.
   Only discover_models: false opts into treating dict keys as a pinned
   allowlist. List / JSON-array-string / Python-literal shapes stay plain
   allowlists.

2. tests/test_issue3718_live_models_custom_probe.py: removed the
   mapping-metadata param that asserted the regression; added two
   real-handler tests: test_dict_models_without_discover_false_does_not_gate
   (dict -> full _LIVE_CATALOG) and test_dict_models_with_discover_false_pins_to_keys
   (bool False / "false" / "no" / "0" -> pinned to keys).

3. docs/architecture/live-models-allowlist.md: documented that list and
   string shapes filter, and a dict filters only with discover_models: false.

Companion test update (blocker reported by the fix itself):

tests/test_byok_model_dropdown.py rightcode-codex entry encoded the removed
dict-as-allowlist behavior (models: {"gpt-5.5-mini": {}} asserting the response
collapsed to just that key). Added discover_models: False to preserve the
provider-scoping intent (no sibling leak) under the new contract.

Red/green verified: removing the dict-branch guard turns
test_dict_models_without_discover_false_does_not_gate red (collapsed catalog);
restoring it turns it green.

Verification: 3718 18 passed; byok 24 passed; neighbour sweep (46 files)
520 passed (2 pre-existing order-dependent flakes reproduce identically on
clean HEAD, verified via git stash); ruff curated gate OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-23 17:48:34 +08:00
happy5318 ff8e75c0be docs(models): document the /api/models/live allowlist runtime contract
Addresses the standing documentation finding: records the four evaluation
signals (discovered catalog defers, plural allowlist filters, singular model
never gates, no allowlist shows full catalog), serialized-list shapes, the
empty-allowlist-is-not-configured rule, and the probe-failure fallback.
Registered in docs/CONTRACTS.md per the #7556 precedent.
2026-09-23 16:58:09 +08:00
starship-s 5fd993cdd5 fix(chat): reconcile conflicting image-row provider payloads
A unique durable row remains one visible row when its sidecar provider payload is stale. Use the state.db payload for replay, cover repeated recovery, and document the image-turn ownership exception.

Assisted-by: Hermes Agent:gpt-6-sol
Assisted-by: Codex:gpt-6-luna
2026-09-23 02:50:40 -06:00
nesquena-hermes 69655b1fc6 Merge master (exp-v0.52.348) into stage/7749-terminal-handoff
# Conflicts:
#	CHANGELOG.md
2026-09-23 08:37:23 +00:00
nesquena-hermes adda410ec0 Merge master (exp-v0.52.347) into stage/7749-terminal-handoff
# Conflicts:
#	CHANGELOG.md
2026-09-23 08:29:47 +00:00
nesquena-hermes 64106a790d Merge master (exp-v0.52.347) into stage/7751-journal-seq
# Conflicts:
#	CHANGELOG.md
#	docs/rfcs/webui-run-state-consistency-contract.md
2026-09-23 08:28:18 +00:00
Frank Song 2bd87a002d fix(run-journal): allocate writer sequence within append transaction 2026-09-23 13:03:31 +08:00
laitekin a0e5e32e46 Merge current master while preserving recoverable hidden polling (#7299) 2026-09-23 12:18:23 +08:00
Frank Song bbca954c5c fix: gate idle recovery on exact runtime status
(cherry picked from commit 35597715018e598bf24f0b708cbd32b039533a99)
2026-09-23 11:57:31 +08:00
Frank Song ca2153ec54 fix: bound sidebar idle recovery for missing terminal events
(cherry picked from commit 1be0e114b32eefe14f94837ed3cf78aadc14ca9b)
2026-09-23 11:57:31 +08:00
Frank Song 5dcda6f537 fix: preserve terminal handoff across idle sidebar refresh
(cherry picked from commit 85f1c2d34b62b0ade85f51ed2cf8c1cf56f5ab9e)
2026-09-23 11:57:31 +08:00
Frank Song 861a10ec34 fix: preserve successor ownership of reused Agents
(cherry picked from commit e4037f1d785aa86074e7cc84025942da5c0cc13a)
2026-09-23 11:56:10 +08:00
Frank Song acdcddf5c9 fix: make Agent cache publication atomic with Stop
(cherry picked from commit c40c43e0eee76a829b113d0119a476a651b60125)
2026-09-23 11:56:10 +08:00
Frank Song 281e91aca3 fix: publish newly constructed agents only after Stop admission
(cherry picked from commit 84a12254fc36aaff628b7e8e43daf48dfd648e67)
2026-09-23 11:56:10 +08:00
Frank Song 9b3951583d fix: fence self-heal worker registration against cancellation
(cherry picked from commit 0fb38b7b5c9453781353464ca5c48c7365359cf1)
2026-09-23 11:56:10 +08:00
nesquena-hermes a6d6b3da85 Merge PR #7374 from Thireus: fix duplicate assistant answer render (#2051) 2026-09-23 02:28:29 +00:00
nesquena-hermes ebcba4386d docs: #7445 CHANGELOG + troubleshooting 'skipped' index status 2026-09-22 22:56:26 +00:00
nesquena-hermes c8b1f87583 Merge PR #7445 from ruizanthony: fix(sqlite): keep state.db readers strictly read-only and stop idle polling 2026-09-22 22:56:02 +00:00
nesquena-hermes 7109a9aed5 Merge PR #7569 from happy5318: perf(run-journal): rebuild live snapshots without quadratic work 2026-09-22 22:27:01 +00:00
laitekin 8396520450 test(streaming): cover profile 409 recovery and stale response bodies (#7299) 2026-09-23 00:00:45 +08:00
laitekin 99f22391d7 Merge remote-tracking branch 'origin/master' into fix/7299-hidden-session-poll 2026-09-22 23:59:23 +08:00
laitekin 3cc825d044 fix(streaming): preserve recovery after ambiguous profile 404s (#7299) 2026-09-22 23:59:23 +08:00
shameez-struggles-to-commit 4f6902bcc0 docs: make the delisted-id guidance actionable
Greptile's P2 was right: 'upgrade past the sync' had no installable
target. Version audit across core tags: every RELEASED Agent (0.20.5 ->
0.21.1, tag v2026.9.7) still carries ox-alpha-free in the curated floor;
the removal exists only on core main, which self-reports the same
0.21.1 version string as the stale tag — a version number alone cannot
distinguish fixed from unfixed. State that plainly and present the
config allowlist as the only verified workaround until a release notes
the 2026-09-09 catalog sync.
2026-09-22 06:38:30 +00:00
shameez-struggles-to-commit f5170004a3 docs: correct Go picker guidance from runtime verification
Verified against a real install (core v0.21.0 + live key + endpoint):
- on Agent releases between v0.20.5 and the 2026-09-09 catalog sync,
  the delisted ox-alpha-free can STILL be offered — via core's own
  live/curated merge AND via _seed_provider_models_from_core() injecting
  the installed core's stale curated ids into WebUI's static list.
  'Upgrade the Agent past the sync' is the correct guidance, not
  'upgrade the WebUI'.
- allowlist precedence re-verified with a real config.yaml on disk
  (group == exactly the allowlisted ids).
- note the 4s foreground rebuild budget: first picker open after a cold
  start can serve last-known catalog while the live rebuild finishes
  out-of-band.
2026-09-22 06:38:30 +00:00
shameez-struggles-to-commit e3c4a0fef1 docs: add OpenCode Go picker troubleshooting entry
User-visible runtime behavior changed in this PR (live catalog first for
Agent >= 0.20.5, resynced static fallback): document both failure
directions users can now hit — listed-but-failing ids (tier/region gates
on the live endpoint, the #7507 follow-up) and missing new ids on
older-AGENT installs — with the diagnostic (hermes --version + authed
curl of /zen/go/v1/models) and fixes (allowlist precedence, Agent
upgrade). Follows the file's Symptom/Why/Diagnostic/Fix/File-a-bug
format.
2026-09-22 06:38:30 +00:00
Thireus ☠ f698c8c9fd docs: write down when a live turn is dropped
AGENTS.md asks for the documentation to move with a runtime-behaviour change, and docs/CONTRACTS.md points at the stable-assistant-turn-anchors RFC for anything that reconciles a live turn with the settled transcript. That is what this change adds, so the rule belongs there.

A new part of the Settlement section says why a preserved live node is not evidence of a running turn, the four facts that have to hold before one is dropped, that ownership is proved from state rather than by comparing two rendered trees, and that only the branches which ADD a turn are gated. It also records the settled-scene half: a prose row that duplicates the final answer, exactly or as a prefix within ten percent of its length, is dropped where both settled renderers take their rows, and live rendering is untouched.
2026-09-21 19:29:01 +01:00
laitekin 9b3c749302 docs(run-journal): specify live-only metering and optional writes (#7272) 2026-09-21 23:03:24 +08:00
laitekin 13d6ba5265 docs(streaming): document hidden-session recovery ownership (#7299) 2026-09-21 23:02:16 +08:00