Commit Graph

704 Commits

Author SHA1 Message Date
Teknium e83816a4d1 review-fix(comments): restore lost #NNNN rationale comments across non-test source (mechanical sweep, condensed, code unchanged)
For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.
2026-09-03 09:44:26 -07:00
Teknium dacee262f7 refactor(web_server): consolidate re-export and router-mount blocks; compact constants prose 2026-09-02 21:36:43 -07:00
Teknium 64ab698ba3 refactor(web_server): compact middleware/auth helpers and lifespan; merge predicate ladders 2026-09-02 21:20:36 -07:00
Teknium 7ee7c1515e refactor(web_server): drop dead legacy re-exports, factor auth-gate message and post-bind best-effort steps 2026-09-02 21:09:46 -07:00
Teknium d6f56549c0 Merge branch 'simp/r2-webserver' into simp/integration2 2026-09-02 17:05:16 -07:00
Teknium f28dfda667 refactor(web_server): flatten nested guards in auth middleware + plugin cache; module docstring describes the split 2026-09-02 16:23:06 -07:00
Teknium 8b34d23366 refactor(web_server): move skills-hub action helpers to web_server_profiles; trim fastapi import block to what web_server still uses 2026-09-02 16:19:10 -07:00
Teknium f9f21dcf25 refactor(web_server): decompose start_server (544 -> 106 LOC) into auth-gate, uvicorn-build, post-start, and runner helpers 2026-09-02 16:15:52 -07:00
Teknium 7d43c20af7 refactor(web_server): move _process_start_marker with the lifecycle cluster 2026-09-02 16:10:10 -07:00
Teknium 2e9294fd7c refactor(web_server): extract serve-process lifecycle helpers to web_server_lifecycle 2026-09-02 16:07:59 -07:00
Teknium 755e83fb5c refactor(web_server): extract files policy, MCP, and profile-scope/catalog helpers to web_server_{files,mcp,profiles} 2026-09-02 16:02:07 -07:00
Teknium 3a056dd466 refactor(web_server): extract gateway topology/actions/process helpers to web_server_gateway; restore late-bound config re-exports 2026-09-02 15:59:08 -07:00
Teknium 5233cbf50f refactor(web_server): extract config schema + model-assignment logic to web_server_config 2026-09-02 15:52:53 -07:00
Teknium 9f92710ca1 refactor(web_server): extract memory-provider dashboard helpers to web_server_memory 2026-09-02 15:46:50 -07:00
Teknium f5a04375cc refactor(web_server): extract oauth pollers/status probes and messaging catalog/onboarding to web_server_oauth, web_server_messaging 2026-09-02 15:45:27 -07:00
Teknium 21f11b4d29 refactor(web_server): extract session-DB access helpers to web_server_sessions 2026-09-02 15:43:37 -07:00
Teknium 6ac699a677 fix(integration): re-export _normalize_dashboard_cron_updates from hermes_cli.web_server 2026-09-02 15:41:15 -07:00
Teknium a7bbe3bf28 refactor(web_server): extract cron dashboard helpers to web_server_cron 2026-09-02 15:39:12 -07:00
Teknium 5608fe7cdf refactor(web_server): extract chat/PTY/WS-auth cluster to web_server_chat 2026-09-02 15:36:53 -07:00
Teknium 2497ec5126 refactor(web_server): extract dashboard SPA/theme/plugin-hub cluster to web_server_dashboard 2026-09-02 15:33:48 -07:00
Teknium beb56b6a00 refactor(web): re-export list_credential_pool from web_server for off-loop tests 2026-09-02 13:49:24 -07:00
Teknium 5c7096e7cf refactor(web): delete dead web_server helpers (_demo, _ws_request_reason, _TERMINAL_BACKEND_NAMES, _mcp_oauth_callback_url_from_base) 2026-09-02 13:33:23 -07:00
Teknium 4fd970c62f refactor(web): absorb single-router web_server helpers into their routers (75 defs); drop dead imports 2026-09-02 13:33:22 -07:00
Teknium c90af45f57 refactor(web): unify the three post-config gateway auto-restart helpers 2026-09-02 13:32:52 -07:00
Teknium f2c506845b refactor(web): unify device-code poller lifecycle into _oauth_poller decorator 2026-09-02 13:32:49 -07:00
Teknium ba4f4b8161 refactor(web): collapse try/except-HTTPException/log/raise boilerplate into _common.http_failure; trim unused fastapi imports 2026-09-02 13:32:46 -07:00
Teknium ba91166b1c refactor(web): hoist stdlib imports in extracted routers; drop unused web_server imports 2026-09-02 13:32:28 -07:00
Teknium e4d8a78967 refactor(web): move /api/logs into web_routers/status.py (logs_router) 2026-09-02 13:32:08 -07:00
Teknium de109d4097 refactor(web): extract chat-tab WebSocket routes into web_routers/chat_ws.py 2026-09-02 13:32:06 -07:00
Teknium 4bae44d654 refactor(web): extract dashboard theme/font/plugin routes into web_routers/dashboard_ui.py 2026-09-02 13:32:05 -07:00
Teknium 94309ad40a refactor(web): extract raw-config + analytics routes into web_routers/analytics.py 2026-09-02 13:32:02 -07:00
Teknium 067028eb22 refactor(web): extract OAuth provider routes into web_routers/oauth.py 2026-09-02 13:32:01 -07:00
Teknium d3b768232e refactor(web): extract status/health/curator/learning/portal routes into web_routers/status.py 2026-09-02 13:30:56 -07:00
Teknium 094dba5a2f refactor(web): extract gateway/update/action-status routes into web_routers/actions.py 2026-09-02 13:30:55 -07:00
Teknium 9de17448dd refactor(web): extract audio/TTS routes into web_routers/audio.py 2026-09-02 13:30:53 -07:00
Teknium feeb1074a3 refactor(web): extract config/env/custom-endpoint routes into web_routers/config_env.py 2026-09-02 13:30:53 -07:00
Teknium 1f4ab19eae refactor(web): extract model assignment routes into web_routers/models.py 2026-09-02 13:30:53 -07:00
Teknium 11bc6bbe11 refactor(web): extract memory-provider setup routes into web_routers/memory_providers.py 2026-09-02 13:30:51 -07:00
Teknium 1f77a129da refactor(web): extract messaging onboarding/platform routes into web_routers/messaging.py 2026-09-02 13:30:50 -07:00
Teknium 0cca195418 refactor(web): extract pairing/webhooks/credential-pool/memory/ops routes into web_routers/ops.py 2026-09-02 13:30:50 -07:00
Teknium 3d5f9269c7 refactor(web): extract files/fs/media routes into web_routers/files.py 2026-09-02 13:30:05 -07:00
peetteerr ff0afff0e4 fix(server): move blocking credential-pool calls off the event loop
Network off (unplugged) froze the backend 17 minutes: the async
/api/credentials/pool endpoints (GET/POST/DELETE) called load_pool()
synchronously on the event-loop thread -> Copilot token exchange ->
blocking urlopen -> getaddrinfo stuck in C for 1016s, immune to
urlopen(timeout=10). WS dropped (1006), sessions detached, even log
writes stalled.

Fix 1 (web_server.py): move the three endpoint bodies into
asyncio.to_thread, matching the file's existing _run pattern.

Fix 2 (copilot_auth.py): _urlopen_bounded() runs the request in a
daemon thread with a wall-clock hard cap (timeout+5s) so DNS hangs
can no longer block any caller indefinitely.

Measured: simulated DNS hang now raises TimeoutError after 6.0s
instead of freezing the loop.
2026-09-03 01:57:09 +05:30
Teknium 1b49ad9be9 fix(dashboard): fold the one-field nous config section into the agent settings tab 2026-09-02 10:22:30 -07:00
unsupportedpastels 323168a289 fix(dashboard): correct copilot-acp sign-in command, honest status card
The Accounts-tab card told users to run 'copilot /login', which is not a
valid invocation — slash-commands only exist inside an interactive session.
Use 'copilot login', the CLI's device-code login subcommand.

The card's status_fn also hardcoded logged_in: False with a static label.
Wire it to get_external_process_provider_status(): claim logged_in only on
positive credential evidence (auth_verified), show which executable Hermes
resolved when merely configured, and say so when the CLI is missing from
PATH entirely.

The rendered cli_command now substitutes the executable the user actually
configured (HERMES_COPILOT_ACP_COMMAND / COPILOT_CLI_PATH) so a custom
binary path gets a copy-pasteable command that matches what Hermes spawns.
2026-09-02 20:51:07 +05:30
kshitijk4poor 95f62ca3bf fix(cron): validate failure_deliver at preflight and dashboard update lanes
Follow-up to the failure_deliver salvage (#100375):

- _preflight_check_delivery also checks the failure lane, so a typo'd
  failure_deliver platform blocks at config-validation time instead of
  surfacing only when a failure occurs — exactly when the notice must
  not be lost. Duplicate lanes are checked once.
- The dashboard cron-update normalizer treats failure_deliver like
  deliver (text normalization; empty clears the optional override
  instead of coalescing), closing the one update path that could write
  an unnormalized value into jobs.json.

4 guard tests; both fixes mutation-checked (neutralize -> red, restore -> green).
2026-09-02 20:16:14 +05:30
Joel Taylor 9d5c58be89 fix(gateway): guard Teams multiplex listener ownership 2026-09-02 07:01:23 -07:00
Teknium 527da60844 fix(cli): report a named profile as running when the default multiplexer serves it
`hermes gateway status`, `hermes gateway list`, `hermes profile list/show`
and the dashboard profiles payload keyed liveness off the profile's own
gateway.pid / gateway_state.json, so a satellite profile served by the
default multiplexer (gateway.multiplex_profiles) showed "not running"
even though the multiplexer is its live inbound process.

Reuse the single lookup the start guard and cron liveness already share —
named_profile_served_by_running_multiplexer() — with an optional
profile_name so list surfaces can ask about any profile, and OR it into
gateway_running for named profiles. Default profile and unserved named
profiles are unchanged.

Salvage of #69118 rebased onto the shared helper (which post-dates it).

Co-authored-by: Isaac Dobson <isaac@dobsonheadlights.com>
Co-authored-by: Mushisushi28 <133449918+Mushisushi28@users.noreply.github.com>
2026-09-02 06:36:16 -07:00
Teknium 62a4599f89 fix(cron): keep profile scope on the standalone fallback pool; desktop ticker stands down for profiles with their own gateway (#100489)
Two mechanisms let the desktop multiplex ticker deliver a secondary
profile's cron output through the default profile's identity:

1. _deliver_result's `asyncio.run` ThreadPoolExecutor fallback (taken when
   the caller already has a running loop — the desktop dashboard shape) ran
   the standalone sender on a fresh thread with NO profile ContextVars: the
   home override and secret scope were gone, so the sender resolved the
   process default's home/token (or, fail-closed under multiplex, raised
   UnscopedSecretError). Wrap the submit in copy_context().run like the
   session-db (:6562), heartbeat (:4650) and parallel-pool (:8314) workers.

2. _start_desktop_cron_ticker ticked EVERY local profile, including ones
   whose own gateway (with live adapters) is running; winning the tick-lock
   race meant the adapter-less desktop ticker delivered standalone. The
   multiplex loop gains an optional per-cycle `profile_gate(name, home)`;
   the desktop wires it to `_check_gateway_running(home)` so such profiles
   are neither ticked nor heartbeated by the dashboard while their gateway
   is alive (re-evaluated every cycle, no restart needed).

Fixes #100489
2026-09-02 06:27:24 -07:00
berg 357062f39e fix(dashboard): multiplex cron fire URL uses the default profile's listener port
Under gateway.multiplex_profiles only the DEFAULT profile's api_server is
bound; secondaries share it via /p/<profile>/ mirrors. _gateway_fire_endpoint
read the port from the TARGET profile's config.yaml/.env and then prefixed
the mirror path, so a secondary with its own API_SERVER_PORT produced a URL
nothing listens on (connection refused on every Chronos fire).

Multiplex is now detected first (config.yaml + the GATEWAY_MULTIPLEX_PROFILES
override via gateway.config._env_multiplex_profiles_override — same
semantics as the gateway loader), and in that mode the port is resolved
from the default root's config/.env with the fallback logged. Per-profile
gateway topology is unchanged.

Salvaged from PR #84755 (@bergusdz), with env-override parity restored and
the silent except replaced by a debug log.
2026-09-02 06:27:24 -07:00
Teknium 4155ea97e8 perf(serve): Desktop backend announces its socket before MCP discovery imports the SDK
`cmd_dashboard` started the background MCP discovery thread before importing
`hermes_cli.web_server`. The thread's first act is the ~350ms `mcp` SDK
import, which holds the GIL against the main thread's own web_server import,
so the HERMES_BACKEND_READY sentinel — and every renderer paint behind it —
moved ~300ms later on every Desktop cold start with any MCP server configured.

Desktop `serve` (headless + HERMES_DESKTOP=1) now arms discovery one second
after the sentinel instead. Starting it AT the bind was measured to give back
most of the gain (the renderer's WebSocket connect + first hydration reads
contend on the same loop). An agent build inside that window pulls the
deferred start forward itself via `wait_for_mcp_discovery`, so the bounded
join and the late-binding tool refresh behave exactly as before. Dashboard
and non-Desktop `serve` keep the eager pre-import ordering.

Minimal reimplementation of the MCP-deferral slice of #96751 by @helix4u;
the plugin-route deferral / 503 middleware / cron-after-bind slices were
measured at ~0-10ms each and are not taken.

Co-authored-by: Gille <4317663+helix4u@users.noreply.github.com>
2026-09-02 06:19:08 -07:00