Feature/gateway code#3317
Conversation
Split gateway into focused packages (config, storage, routers, core) so turn execution, inbound routing, and background poll logic live under gateway/core/, with function-oriented settings loading and updated imports. Co-authored-by: Cursor <cursoragent@cursor.com>
Greptile code reviewThis repo uses Greptile for automated review. Before merge, aim for Confidence Score: 5/5 with zero unresolved review threads — see CONTRIBUTING.md. Run a review — add a PR comment with: Give it ~5-10 minutes (sometimes longer) for results, then fix feedback and re-trigger until you reach Confidence Score: 5/5. Optional: automate with the greploop skill. |
Resolve conflicts by keeping the follow-up gateway work: dedicated-process only startup, improved gateway logging, and no REPL co-located gateway. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🧠 @davincios opened a PR. Maintainers feared them. CI genuflected. It merged. 🚨 👋 Join us on Discord - OpenSRE : hang out, contribute, or hunt for features and issues. Everyone's welcome. |
Greptile SummaryThis PR replaces the previous FastAPI/webhook gateway with a fully long-poll-only Telegram gateway. The monolithic
Confidence Score: 3/5Safe to merge once the unbounded recursion in The provider alias resolution in
|
| Filename | Overview |
|---|---|
| gateway/agent/gateway_agent_adapters.py | Provides adapter classes for the headless agent harness; contains _resolve_provider_models which recurses without cycle detection — a circular provider alias would overflow the stack. |
| gateway/config/get_gateway_settings.py | Loads Telegram gateway settings from env + integration store with solid validation; contains a dead-code branch (if not settings.bot_token) unreachable after load_gateway_settings raises on missing token. |
| gateway/session/resolve_or_rotate_session.py | Applies security decision side effects and resolves/rotates sessions; uses a magic-string sentinel "__ROTATE_SESSION__" as an inter-module protocol that is fragile if the string ever diverges. |
| gateway/agent/dispatch_gateway_msg_to_agent.py | Orchestrates a full headless agent turn with solid exception handling, Sentry reporting, and graceful sink finalization. |
| gateway/agent/gateway_action_tools.py | Defines gateway-local shell and investigation tools with clear deny/allow policy, timeout enforcement, and output truncation. |
| gateway/polling/telegram_poller/poller.py | Long-poll transport with conflict backoff and throttled warning logs; bot token embedded in the URL path may appear in httpx exception strings under some network failure modes. |
| gateway/polling/telegram_polling_runtime.py | Wires shared polling resources (client, db, executor) and provides clean initialize/shutdown lifecycle callbacks. |
| gateway/storage/session/resolver.py | Session resolution backed by SQLite bindings with correct user_id keying and safe rotate logic. |
| gateway/session/enforce_inbound_telegram_message_security.py | Inbound authorization with /pair, /new, /help commands and audit logging; env user IDs are applied in-memory without accidental persistence. |
| gateway/agent/gateway_output_sink.py | Throttled streaming sink using edit_message_text with a lock protecting the Telegram API call; clean finalize/render_error paths. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant TB as Telegram Bot API
participant TP as TelegramPoller
participant BG as TelegramGatewayBackground
participant H as handle_polled_inbound_msg
participant Auth as enforce_security
participant SR as SessionResolver
participant D as dispatch_gateway_msg_to_agent
participant Sink as GatewayOutputSink
loop Long Poll
TP->>TB: "getUpdates (timeout=30, offset)"
TB-->>TP: Update events
end
TP-->>BG: list[TelegramInboundMessage]
BG->>H: event (per update)
H->>Auth: enforce_inbound_telegram_message_security
Auth-->>H: InboundDecision
H->>SR: resolve_or_rotate_session
SR-->>H: ReplSession or None
H->>Sink: init, send Working message
Sink->>TB: sendMessage
H->>D: dispatch_gateway_msg_to_agent
D->>D: inject_gateway_chat_context
loop Streaming
D->>Sink: stream chunks
Sink->>TB: editMessageText throttled
end
D->>Sink: finalize
Sink->>TB: editMessageText final
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant TB as Telegram Bot API
participant TP as TelegramPoller
participant BG as TelegramGatewayBackground
participant H as handle_polled_inbound_msg
participant Auth as enforce_security
participant SR as SessionResolver
participant D as dispatch_gateway_msg_to_agent
participant Sink as GatewayOutputSink
loop Long Poll
TP->>TB: "getUpdates (timeout=30, offset)"
TB-->>TP: Update events
end
TP-->>BG: list[TelegramInboundMessage]
BG->>H: event (per update)
H->>Auth: enforce_inbound_telegram_message_security
Auth-->>H: InboundDecision
H->>SR: resolve_or_rotate_session
SR-->>H: ReplSession or None
H->>Sink: init, send Working message
Sink->>TB: sendMessage
H->>D: dispatch_gateway_msg_to_agent
D->>D: inject_gateway_chat_context
loop Streaming
D->>Sink: stream chunks
Sink->>TB: editMessageText throttled
end
D->>Sink: finalize
Sink->>TB: editMessageText final
Comments Outside Diff (4)
-
gateway/agent/gateway_agent_adapters.py, line 31-44 (link)Unbounded recursion in provider alias resolution. If
effective_llm_providerreturns a provider that eventually aliases back to an earlier value (A→B→A), this recurses until Python's recursion limit is hit and raises aRecursionError. That exception propagates out ofenvironment_block()and is only caught several frames up indispatch_gateway_msg_to_agent, which silently fails every turn with a user-visible error until the configuration is fixed. Adding avisitedset to detect cycles prevents the stack overflow and makes the failure observable at the right layer. -
gateway/config/get_gateway_settings.py, line 170-174 (link)Unreachable dead-code branch.
load_gateway_settings()callschoose_bot_token(), which raisesGatewayConfigurationErrorwhen the token is empty. That exception is caught on line 155 and causes an earlyreturn None. A settings object with an emptybot_tokencan therefore never be returned, making theif not settings.bot_tokenguard permanently skipped. Remove or replace it with an assertion so the intent is clear. -
gateway/session/enforce_inbound_telegram_message_security.py, line 136-142 (link)Magic-string sentinel couples two modules implicitly.
"__ROTATE_SESSION__"is produced here and consumed inresolve_or_rotate_session.pyas a raw string comparison. If either side is ever updated without the other (e.g. a typo, a refactor), the/newcommand silently falls through to the normal agent dispatch path instead of rotating the session. Consider extracting this as a module-level constant or replacing the string protocol with a dedicated field onInboundDecisionsuch asrotate_session: bool = False.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
-
gateway/polling/telegram_poller/poller.py, line 44-52 (link)Bot token embedded in the URL path may appear in exception strings.
httpx.ConnectErrorand similar transport exceptions sometimes include the request URL in their__str__representation. Sinceurl = _API.format(token=self._token, ...)embeds the token in the path, a network failure logged by_log_transientwould expose it in plain text. Consider storing a separate redacted URL for logging and only using the real URL for the actual request.
Reviews (1): Last reviewed commit: "Merge main into feature/gateway-code aft..." | Re-trigger Greptile

Fixes #
Describe the changes you have made in this PR -
Demo/Screenshot for feature changes and bug fixes -
Code Understanding and AI Usage
Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?
If you used AI assistance:
Explain your implementation approach:
Checklist before requesting a review
Note: Please check Allow edits from maintainers if you would like us to assist in the PR.