Skip to content

fix(#5000): relay mirrored gateway approvals after stream loss - #5041

Closed
rodboev wants to merge 3 commits into
nesquena:masterfrom
rodboev:pr/5000-gateway-approval-run-context
Closed

rodboev wants to merge 3 commits into
nesquena:masterfrom
rodboev:pr/5000-gateway-approval-run-context

Conversation

@rodboev

@rodboev rodboev commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Thinking Path

  • Gateway approval cards already survive on the WebUI side as mirrored pending entries, but /api/approval/respond still insists on walking back through session.active_stream_id to find the run.
  • Current origin/master proves the narrow failure: if the stream pointer is gone, the handler returns gateway_run_unavailable even while the mirrored approval still carries the original run_id.
  • The final fix uses that mirrored run_id before the true no-run 409 path, then settles the local approval lifecycle too, so the card does not come back after a successful remote relay.

What Changed

  • api/route_approvals.py: add a narrow mirrored-approval run lookup keyed by approval_id
  • api/routes.py: fall back to the mirrored gateway approval's run_id, preserve the existing 409 containment, and settle the local approval queue after a successful relay
  • tests/test_gateway_approval_legacy_path.py: add regressions for the lost-active_stream_id, still-relayable path and the benign gateway-mode no-pending path, including queue cleanup and agent wake-up assertions

Why It Matters

Gateway-backed approval prompts should not dead-end just because the live stream pointer vanished after the card rendered. This keeps already-visible approval controls usable, while still clearing the mirrored approval state once the remote run resumes and preserving the existing 409 for approvals that truly have no run left to relay.

Verification

pytest tests/test_gateway_approval_legacy_path.py tests/test_issue4771_local_approval_regression.py tests/test_gateway_approval_runs_api.py -v --timeout=60

Full-suite CI context, not a required local check unless explicitly requested: pytest tests/ -v --timeout=60.

Upstream

Closes #5000.

Model Used

GPT 5.5 via Codex CLI

@greptile-apps

greptile-apps Bot commented Jun 27, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR keeps gateway approval responses working after the live stream pointer is gone. The main changes are:

  • Added mirrored pending approval lookup by approval_id.
  • Used the mirrored run_id as a relay fallback in approval responses.
  • Cleared the local mirrored approval state after a successful gateway relay.
  • Added tests for stream-loss relay recovery and empty gateway-mode clicks.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
api/route_approvals.py Adds session-scoped lookup for a mirrored gateway approval run.
api/routes.py Falls back to mirrored approval state for gateway relay and clears local state after success.
tests/test_gateway_approval_legacy_path.py Adds tests for lost stream recovery and gateway-mode no-pending behavior.

Reviews (2): Last reviewed commit: "test(#5000): keep gateway approval regre..." | Re-trigger Greptile

nesquena-hermes added a commit that referenced this pull request Jun 27, 2026
Release: relay mirrored gateway approvals after stream loss (#5041, fixes #5000)
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Shipped in v0.51.699 — merged via release PR #5044 and deployed to prod. Thanks @rodboev! 🙌

Full gate: Codex SAFE TO SHIP (verified the stream-alive path is unchanged, the stream-lost relay only uses the mirrored approval scoped to the same session + approval id with no cross-session misroute, missing-origin approvals still return gateway_run_unavailable, and auth/CSRF gates are intact in the shared POST path), ruff CLEAN, full suite 10766 passed.

Closes #5041 + #5000. Clean targeted fix — keeping the approval card actionable across stream loss is exactly the right call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(gateway/approval): approve/deny relay fails on every approval — "active run unavailable"

2 participants