Skip to content

feat(session_context): add set/reset_current_turn_session_key public wrappers - #32927

Open
Isla-Liu wants to merge 4 commits into
NousResearch:mainfrom
Isla-Liu:feat/session-context-public-turn-setters
Open

feat(session_context): add set/reset_current_turn_session_key public wrappers#32927
Isla-Liu wants to merge 4 commits into
NousResearch:mainfrom
Isla-Liu:feat/session-context-public-turn-setters

Conversation

@Isla-Liu

Copy link
Copy Markdown

This adds public wrappers for the per-turn session-identity ContextVar in
gateway.session_context, mirroring the structural pattern that
tools/approval.py uses for the approval-session ContextVar.

Motivation

What ships

  • gateway.session_context.set_current_turn_session_key(key: str) -> Token
  • gateway.session_context.reset_current_turn_session_key(token: Token) -> None
  • Test coverage: round-trip, nested set+reset, empty-string normalization,
    None-normalized-to-empty.
  • No change to _SESSION_KEY itself or to existing callers; the wrappers
    are additive.

Naming

  • Deliberately distinct from tools/approval.py's
    set_current_session_key — the two ContextVars carry different
    concerns and downstream callers may need to set both in the same
    scope. turn_session (this module) vs session (approval) keeps
    imports unambiguous.

Follow-up

Refs

@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery labels May 27, 2026
@Isla-Liu

Copy link
Copy Markdown
Author

Quick downstream context on why this PR exists, plus a side-effect read so the merge call is easy.

Why these wrappers. hermes-webui#2968 (nesquena/hermes-webui#2968) needs to bind a per-turn session_key onto gateway.session_context._SESSION_KEY for server-initiated wakeup turns. Background tasks completing with notify_on_complete=true can spawn a turn from a thread whose ambient ContextVar carries a stale value, misrouting the wakeup SSE to the wrong session in a narrow multi-tab window. The current WebUI PR binds via direct _SESSION_KEY.set(...); the WebUI maintainer flagged that as a private-API touch and asked for a public agent-side setter before that import lands. These wrappers are that setter.

What ships — additive only.

  • Two new public functions in gateway/session_context.py: set_current_turn_session_key(session_key) returning a contextvars.Token, and reset_current_turn_session_key(token) taking it back. Mirrors the structural pattern of tools/approval.py's session-key setters.
  • 4 new tests in tests/test_session_context_public_turn_setters.py covering set/reset round-trip, copy_context isolation, nesting, and reset-with-stale-token.

What does NOT change.

  • _SESSION_KEY itself — still private; we only add public wrappers around it.
  • No existing imports or call sites in hermes-agent are touched.
  • No behavior change in turn handling; the new wrappers have no in-tree consumer today.
  • tools/approval.py's set_current_session_key / reset_current_session_key for the approval-session ContextVar are untouched. The wrappers here carry turn_session in the middle on purpose: the unqualified name is already taken in tools/approval.py for a different ContextVar, so a collision-free name was required.

Side effects. None expected — pure indirection over an existing ContextVar, no shared state, no thread-pool implications beyond what the ContextVar already has. If _SESSION_KEY is ever refactored, the wrappers give a stable indirection point for downstream.

Downstream follow-up. Once this merges, the WebUI side replaces the private _SESSION_KEY.set(...) import with the public setter in a small follow-up PR — ~1 line of meaningful change in api/streaming.py:_set_turn_session_identity plus the matching reset.

Refs: hermes-webui#2968 — nesquena/hermes-webui#2968

@Isla-Liu
Isla-Liu marked this pull request as ready for review May 27, 2026 02:37
Copilot AI review requested due to automatic review settings May 27, 2026 02:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds public, per-turn session-key ContextVar setter/resetter APIs and validates expected ContextVar behavior via unit tests.

Changes:

  • Introduce set_current_turn_session_key() / reset_current_turn_session_key() wrappers around gateway.session_context._SESSION_KEY.
  • Add tests for round-trip, nesting, and normalization behavior (including None input).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
gateway/session_context.py Adds public per-turn session key setter/resetter APIs returning/resetting contextvars.Token.
tests/test_session_context_public_turn_setters.py Adds tests exercising per-turn session key bind/reset behavior, including nesting and None handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
Comment thread tests/test_session_context_public_turn_setters.py Outdated
Comment thread tests/test_session_context_public_turn_setters.py Outdated
@Isla-Liu
Isla-Liu requested a review from Copilot May 27, 2026 06:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py
Comment thread tests/test_session_context_public_turn_setters.py
@Isla-Liu
Isla-Liu requested a review from Copilot May 27, 2026 07:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment thread tests/test_session_context_public_turn_setters.py
Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
@Isla-Liu
Isla-Liu requested a review from Copilot May 28, 2026 01:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
Comment thread gateway/session_context.py Outdated
Comment thread tests/test_session_context_public_turn_setters.py Outdated
Comment thread tests/test_session_context_public_turn_setters.py Outdated
Isla-Liu added 4 commits May 28, 2026 17:18
Adds a public wrapper pair for the per-turn session-identity ContextVar in gateway.session_context, mirroring the structural pattern that tools/approval.py uses for the approval-session ContextVar.

Naming: deliberately distinct from approval.py's set_current_session_key -- the two ContextVars carry different concerns and downstream callers will eventually need to set both. 'turn_session' disambiguates from the approval-session.

Motivation: hermes-webui PR NousResearch#2968 (nesquena/hermes-webui#2968) currently binds per-turn session identity by importing _SESSION_KEY and calling .set() directly, which the maintainer flagged as a private-API touch. This wrapper closes that gap; the webui-side refactor lands as a follow-up commit on that PR once this lands.
Anchors:
- Copilot r3308087275/r3308087295: type signatures now accept Optional[str]
  and use Token[str]; import Optional. Public setter docstring also notes
  None is normalised to empty string.
- Copilot r3308087305: rewrite turn_session vs session paragraph in
  set_current_turn_session_key docstring to reference the actual API
  surface (turn_session_key suffix, _SESSION_KEY ContextVar) so wording
  matches the names callers see.
- Copilot r3308087325/r3308087343: harden test_set_and_reset_round_trip
  by capturing the surrounding ContextVar value before set() and asserting
  identity equality after reset() instead of relying on a !=
  'session-abc' check that could flake when an outer context already
  binds that string.
Anchors:
- Copilot r3308922402: widen turn-session token typing for _UNSET sentinel
- Copilot r3308922430: widen reset token typing for _UNSET sentinel
- Copilot r3308922450: align _SESSION_KEY ContextVar token type with sentinel
- Copilot r3308922477: assert session key behavior through public get_session_env
@Isla-Liu
Isla-Liu force-pushed the feat/session-context-public-turn-setters branch from 6e8c79a to f8ffb2c Compare May 28, 2026 09:19
@Isla-Liu
Isla-Liu requested a review from Copilot May 28, 2026 09:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for identifying a real downstream API seam. Current WebUI master still imports gateway.session_context._SESSION_KEY directly in api/streaming.py:1825 and resets it at :1846.

Problems

  • The PR is DIRTY and its broad sentinel/ContextVar rewrite (gateway/session_context.py PR head :43-74, :228) predates current main's session-context expansion and hardening (gateway/session_context.py:73-121, :157-301). Salvaging that rewrite would risk discarding current behavior unrelated to the requested API.
  • turn_session_key is a third public API at PR head gateway/session_context.py:143-150; the documented downstream contract only uses the explicit setter/resetter pair.

Suggested changes

  • Salvage only the additive setter/resetter pair against current main, preserving the current _UNSET, _VAR_MAP, and fallback behavior.
  • Omit the context manager unless a concrete caller needs it.

This is an automated hermes-sweeper review.

from contextvars import ContextVar, Token
from typing import Iterator, Optional

class _UnsetType:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not carry this sentinel/type migration into the salvage. The requested change is the public session-key wrapper pair, while current main has since expanded and hardened this ContextVar module; preserve its current state representation and add the wrappers only.

_SESSION_KEY.reset(token)


@contextmanager

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The downstream contract described by this PR uses the explicit setter/resetter pair. Please omit this additional public context-manager API unless a concrete consumer needs it.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/sessions Session lifecycle, resume, persistence, history labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants