HERMES-GIELIE/api
ai-ag2026 a31cdb7765 fix(terminal): unsubscribe when the SSE header write fails after attaching
Adversarial review of the previous commit found a leak it introduced.

`attach_terminal()` subscribes and only then are the response headers written.
A client that dropped in that instant makes `end_headers()` raise
BrokenPipeError/ConnectionResetError, and because the `try/finally` started
*after* those writes, the exception escaped `_handle_terminal_output` with the
queue still in `_subscribers`. That pins `unwatched_since` at None — only
`unsubscribe()` on an empty subscriber list resets it — so the terminal became
permanently unreapable: the exact fd/thread leak (#4633) this reaper exists to
prevent, and strictly worse than the TOCTOU the previous commit fixed, since
that at least still allowed cleanup.

The try now starts immediately after the attach, so every exit path
unsubscribes. Regression test drives a handler whose `end_headers()` raises and
asserts the subscriber list is empty, `unwatched_since` is restored, and the
terminal is reapable again once the grace elapses. It fails against the
previous ordering.
2026-07-25 03:17:30 +02:00
..
__init__.py
agent_health.py fix: fail closed on wrapped gateway pid helpers 2026-07-14 16:36:23 +08:00
agent_runtime.py fix(runtime): ignore in-memory agent module swaps 2026-07-16 22:28:35 +08:00
agent_sessions.py Release exp-v0.52.40: ACP sessions in sidebar (#5939) + date-stamped Claude 3.0 reasoning fix (#5934) (#5951) 2026-07-11 15:20:41 -07:00
auth.py Release exp-v0.52.43: trusted-header auth / reverse-proxy SSO (#5568, #3351) (#5956) 2026-07-11 16:34:14 -07:00
auth_oidc.py Release: OIDC allowlist whitespace fix (#6244, @webtecnica) (#6259) 2026-07-18 10:36:17 -07:00
background.py
background_process.py fix(wakeup): recover terminal process completions after restart (#6287) 2026-07-18 20:07:54 -07:00
clarify.py
commands.py fix(webui): guard non-dict resolve_moa_preset result in resolve_moa_config 2026-07-01 07:54:48 -05:00
compression_anchor.py Address compaction marker and redaction review 2026-06-26 00:12:09 +00:00
compression_recovery.py Live Stream: add compression recovery action 2026-07-04 21:42:32 +08:00
config.py Merge remote-tracking branch 'origin/master' into stage/6040 2026-07-23 02:26:42 +00:00
crash_visibility.py fix(webui): crash visibility — faulthandler + thread excepthook + exit audit (#4633) 2026-07-01 18:01:39 +00:00
dashboard_probe.py
extension_sidecar_auth.py feat(extensions): token-v1 proxy→sidecar authentication boundary (#6331) 2026-07-20 17:49:23 +00:00
extensions.py feat(extensions): token-v1 proxy→sidecar authentication boundary (#6331) 2026-07-20 17:49:23 +00:00
gateway_chat.py fix(#6008): keep gateway cancel authority stable across startup teardown 2026-07-22 12:33:26 -04:00
gateway_restart.py fix: harden gateway restart recovery targeting 2026-07-14 16:01:56 +08:00
gateway_watcher.py fix(sessions): open state.db read-only for lineage reads + watcher projection 2026-07-08 20:17:45 +00:00
goals.py
helpers.py Release: raster-data-URI redaction fast-path (#6311, @inch772) (#6367) 2026-07-20 16:30:04 +00:00
kanban_bridge.py rebase(#2814): resolve i18n onto current master + add kanban_view_* keys to all 13 locales 2026-06-23 23:40:45 +00:00
metering.py feat(#6006): instrument send-to-first-token latency 2026-07-13 17:56:44 -04:00
models.py feat: render process wakeups as collapsed summary cards (#6350) 2026-07-23 20:52:51 +00:00
oauth.py perf(providers): invalidate cache on oauth credential changes 2026-07-13 19:58:41 +08:00
office_documents.py #5142: office-doc preview + safe docx editing (#540), rebased on master; optional deps 2026-07-02 01:15:57 +00:00
onboarding.py Cover onboarding with atomic config writes 2026-07-18 13:47:04 +02:00
passkeys.py Release Batch D: terminal resource-leak fix + fsync atomic writers (#5835, #5843) (#5848) 2026-07-09 10:54:06 -07:00
paths.py fix(config): restore read-only-target protection for atomic writes 2026-07-18 20:32:56 +02:00
plugin_providers.py
plugins.py
process_event_utils.py feat: render process wakeups as collapsed summary cards (#6350) 2026-07-23 20:52:51 +00:00
profiles.py stage: merge #5797 2026-07-22 18:45:24 +00:00
providers.py perf(providers): invalidate cache on oauth credential changes 2026-07-13 19:58:41 +08:00
request_diagnostics.py perf(webui/session-load-latency) tier4: fix CI failures — lint B009/B905 + _emit_slow format args 2026-07-09 04:22:21 +00:00
rollback.py
route_approvals.py fix(#6008): serialize identity-less approval relays 2026-07-22 15:06:33 -04:00
route_session_list_cache.py fix(cache): keep streaming TTLs above poll cadence 2026-07-15 20:59:59 +00:00
routes.py fix(terminal): unsubscribe when the SSE header write fails after attaching 2026-07-25 03:17:30 +02:00
run_journal.py Release: run-journal summary cache (#6291, @sjungwon03) (#6355) 2026-07-20 09:12:32 +00:00
runner_client.py
runtime_adapter.py
session_discoverability.py Release Batch D: terminal resource-leak fix + fsync atomic writers (#5835, #5843) (#5848) 2026-07-09 10:54:06 -07:00
session_events.py
session_export_html.py #4968: export chat to self-contained themed HTML, rebased on master 2026-07-02 02:36:09 +00:00
session_lifecycle.py fix(#5543): fire-and-forget commit_session_memory + drain-safe managed stop 2026-07-04 21:40:21 +00:00
session_ops.py fix: preserve lazy alignment semantics 2026-07-17 15:36:55 -06:00
session_recovery.py Merge latest master into compression recovery action 2026-07-05 10:23:15 +08:00
shares.py fix(share): harden _embed_share_media with path allow-list + mime validation (#6174) 2026-07-23 01:21:59 +00:00
skill_usage.py
sse_chunked.py
startup.py
state_sync.py fix(state-sync): mirror WebUI API call counts 2026-07-07 19:48:19 +00:00
streaming.py feat: render process wakeups as collapsed summary cards (#6350) 2026-07-23 20:52:51 +00:00
system_health.py fix: keep psutil optional for system health 2026-06-26 20:49:13 +00:00
terminal.py fix(terminal): close the reaper's selection→reconnect→close TOCTOU 2026-07-25 00:33:41 +02:00
todo_state.py
turn_journal.py
updates.py Release: pip-installable packaging metadata (#6337, @rodboev) (#6344) 2026-07-20 02:17:52 +00:00
upload.py Release: write Office upload sidecars (#5734, #540) (#5859) 2026-07-09 15:57:21 -07:00
usage.py
webui_session_db.py fix: preserve compression recovery child markers in sidecar rebuild 2026-07-05 06:45:50 +08:00
workspace.py #5142: office-doc preview + safe docx editing (#540), rebased on master; optional deps 2026-07-02 01:15:57 +00:00
workspace_git.py fix(workspace-git): hide git subprocess console windows on Windows (#5692) 2026-07-07 02:07:39 +00:00
worktrees.py fix(worktrees): unlock before remove so WebUI-created worktrees can be reaped 2026-07-13 17:47:58 +00:00