refactor(gateway): give _pinned_channel_inputs explicit inputs

The two pin helpers encode one rule (a human turn records, an internal
turn reuses) but took it in two shapes: _pinned_session_context_prompt
gets `internal` as a keyword while _pinned_channel_inputs took the whole
event and read getattr(event, ...) itself. Match the sibling:
(session_key, channel_prompt, source, *, internal), with the call sites
passing the event's values. MessageEvent.channel_prompt/internal and
SessionSource.parent_chat_id are declared dataclass fields, so the
getattr guards (including the new context-prompt call site) go too.
This commit is contained in:
kshitijk4poor
2026-09-26 21:24:13 +05:30
committed by kshitij
parent 9c13cb21d4
commit e3ffee06f2
2 changed files with 11 additions and 10 deletions

View File

@@ -641,7 +641,9 @@ class GatewayAgentCacheMixin:
self._session_state(session_key).conversation.ephemeral_pin = (_eph_key, text)
return text
def _pinned_channel_inputs(self, session_key, event, source):
def _pinned_channel_inputs(
self, session_key: Optional[str], channel_prompt: Optional[str], source: SessionSource, *, internal: bool,
):
"""``(channel_prompt, source)`` for this turn's agent run.
The ephemeral system prompt also appends ``channel_prompt`` and the ``channel_overrides``
@@ -649,20 +651,17 @@ class GatewayAgentCacheMixin:
``channel_prompt=None`` and a source without ``parent_chat_id``, so they dropped both and
toggled the system prompt like the context pin did. Human turns record their inputs;
internal turns reuse them."""
channel_prompt = getattr(event, "channel_prompt", None)
if not session_key:
return channel_prompt, source
if not getattr(event, "internal", False):
self._session_state(session_key).conversation.channel_pin = (
channel_prompt, getattr(source, "parent_chat_id", None),
)
if not internal:
self._session_state(session_key).conversation.channel_pin = (channel_prompt, source.parent_chat_id)
return channel_prompt, source
state = self._peek_session_state(session_key)
pin = state.conversation.channel_pin if state else None
if pin is None:
return channel_prompt, source
pinned_prompt, pinned_parent = pin
if pinned_parent and not getattr(source, "parent_chat_id", None):
if pinned_parent and not source.parent_chat_id:
from gateway.session_identity import replace_source
source = replace_source(source, parent_chat_id=pinned_parent)
return pinned_prompt, source

View File

@@ -2088,7 +2088,7 @@ class GatewayTurnMixin:
# The context prompt render is pinned per session, keyed by a hash of the renderer inputs, so
# the system prompt cannot drift turn-over-turn; a miss (thread rename, /sethome) re-renders.
context_prompt = self._pinned_session_context_prompt(
context, _redact_pii, session_key, internal=bool(getattr(event, "internal", False)),
context, _redact_pii, session_key, internal=event.internal,
)
# Per-turn notes ride the user message via the api_content sidecar, NOT context_prompt
@@ -2208,7 +2208,9 @@ class GatewayTurnMixin:
# turn preparation gates have passed when the agent runner is entered.
event._heartbeat_execution_started = True
# Internal events reuse the last human turn's channel inputs (see _pinned_channel_inputs).
_turn_channel_prompt, _turn_source = self._pinned_channel_inputs(session_key, event, source)
_turn_channel_prompt, _turn_source = self._pinned_channel_inputs(
session_key, event.channel_prompt, source, internal=event.internal,
)
agent_result = await self._run_agent(
message=message_text, context_prompt=prepared.context_prompt, history=history, source=_turn_source,
session_id=_run_start_session_id, session_key=session_key,
@@ -3877,7 +3879,7 @@ class GatewayTurnMixin:
next_message_id = self._reply_anchor_for_event(pending_event)
next_inbound_id = str(pending_event.message_id) if getattr(pending_event, "message_id", None) else None
next_channel_prompt, next_source = self._pinned_channel_inputs(
next_session_key, pending_event, next_source,
next_session_key, pending_event.channel_prompt, next_source, internal=pending_event.internal,
)
next_message_type = getattr(pending_event, "message_type", None)