background_agents.game_turn_agent module

GameTurnAgent – roster-coverage validator for game choice buttons.

Subscribes to game:turn:complete pub/sub events. Proofreading of individual choices (strip markdown, trim emojis, truncate labels) is now done inline by the renderer; the helper _proofread_choice / _first_emoji functions in this module remain available but the agent’s runtime job is validation only. When a game turn completes, this agent:

  1. Reads any still-present draft choice blocks from Redis (game:choices:draft:{channel_id}) to see which players were covered

  2. Validates roster coverage against the session: - All ACTIVE/IDLE players must have choices - DORMANT players should not have choices

  3. Pings Star via a system message if active/idle players are missing choices

If the draft key was already consumed by the renderer, the agent trusts the renderer and skips validation.

class background_agents.game_turn_agent.GameTurnAgent(discord_platform=None)[source]

Bases: object

Background agent that proofreads and validates game-turn choices.

Subscribes to the game:turn:complete Redis pub/sub channel and, for each completed turn, cleans the channel’s draft choices (via _proofread_choice()) and checks that every active player has a choice – pinging Star through the Discord platform when coverage is missing. Constructed by the agents service bootstrap in agents_main.py and driven by its long-lived listener task (see start()/_listen()); the Redis client is injected at start() time.

Parameters:

discord_platform (Any)

__init__(discord_platform=None)[source]

Initialize the roster-coverage validator agent.

Stores the Discord platform handle (used by _ping_star() to send a system message into a channel when active players are missing choices) and sets the listener task slot and running flag to their idle defaults. The Redis client is not supplied here; it is injected later in start(). No subscriptions or I/O happen at construction time.

Constructed by the agents service bootstrap in agents_main.py.

Parameters:

discord_platform (Any) – Discord platform object exposing a client that can resolve and send to channels. When None, _ping_star() logs a warning and skips the ping.

Return type:

None

async start(redis)[source]

Start the pub/sub listener that validates completed game turns.

Stores the injected async Redis client, marks the agent running, and spawns the long-lived _listen() coroutine as a named game-turn-agent asyncio.Task. This is the agent’s entry point: once started it watches the game:turn:complete channel and reacts to each turn-completion event. No subscription happens until the task runs, so this returns immediately after scheduling.

Called by the agents service bootstrap in agents_main.py (the AgentsService start path), which constructs the agent and then awaits start(redis).

Parameters:

redis (Any) – An async Redis client used both for pub/sub subscription and for reading the per-channel draft-choice list during validation.

Return type:

None

Returns:

None.

async stop()[source]

Stop the agent and tear down its listener task.

Clears the running flag so _listen() exits its loop, then cancels the background listener task and awaits it, swallowing the resulting asyncio.CancelledError. Used for clean shutdown so the pub/sub subscription and its task do not leak when the service stops.

Called by the agents service shutdown path in agents_main.py (the AgentsService stop/cleanup sequence).

Return type:

None

Returns:

None.

async background_agents.game_turn_agent.publish_turn_complete(redis, channel_id, narrative, game_id='', game_name='', turn_number=0, active_player_names=None)[source]

Publish a turn-completion event onto the GameTurnAgent’s pub/sub channel.

Serializes the turn metadata (channel, a truncated narrative preview, game id/name, turn number, the active player roster, and a timestamp) and publishes it on TURN_COMPLETE_CHANNEL (game:turn:complete) so the GameTurnAgent listener can validate roster coverage for the turn. No-ops when redis is None; publish failures are caught and logged so a Redis hiccup never blocks the send pipeline.

Called from the main message pipeline in message_processor/generate_and_send.py once Star’s narrative has been sent for a game turn.

Parameters:
  • redis (Any) – An async Redis client, or None to skip publishing.

  • channel_id (str) – The Discord channel id the turn belongs to.

  • narrative (str) – Star’s turn narrative; truncated to 3000 chars in the payload.

  • game_id (str) – Optional game identifier carried through to the event.

  • game_name (str) – Optional human-readable game name carried through.

  • turn_number (int) – The turn index, included in the payload and debug log.

  • active_player_names (list[str] | None) – Names of players active this turn, used by the agent for roster-coverage validation; None becomes an empty list.

Return type:

None

Returns:

None.