status_manager

AI-generated Discord status with glitch-cycling effects.

Platform-agnostic core with Discord-specific presence integration. Started as a background task by the Inference service (inference_main.InferenceService); presence updates are published over the event bus via the worker’s ProxyPlatformAdapter.

class status_manager.StatusConfig(min_interval=60, max_interval=3600, max_length=128, emoji='🌟', glitch_interval=300, num_variants=200, name_glitch_interval=30, enable_name_glitch=True)[source]

Bases: object

Tunable knobs for the AI status generator and glitch cycler.

Holds the cadence and sizing parameters that drive StatusManager: how often a fresh LLM-generated base status is requested (max_interval), how often the glitch-cycled variant is pushed to Discord (glitch_interval), how many glitch variants to precompute (num_variants), the presence emoji, and the Discord custom-status length cap (max_length). It is a pure data container with no behavior; an instance is passed to StatusManager.__init__ or defaulted there when omitted. Instantiated by the inference service when it constructs the manager and by the presence test suite (tests/test_status_presence.py).

Parameters:
  • min_interval (int)

  • max_interval (int)

  • max_length (int)

  • emoji (str)

  • glitch_interval (int)

  • num_variants (int)

  • name_glitch_interval (int)

  • enable_name_glitch (bool)

min_interval: int = 60
max_interval: int = 3600
max_length: int = 128
emoji: str = '🌟'
glitch_interval: int = 300
num_variants: int = 200
name_glitch_interval: int = 30
enable_name_glitch: bool = True
class status_manager.StatusManager(openrouter, discord_adapter=None, config=None, leader_guard=None)[source]

Bases: object

Generate, glitch-cycle, and publish the bot’s Discord presence.

Drives the dark-AI-persona custom status: periodically asks the LLM (via the injected openrouter client’s chat) for a fresh themed base line, precomputes a pool of glitched variants from it, and rotates through them on a timer so the presence visibly shimmers without a new LLM call each tick. The actual presence write goes through the injected discord adapter; in the microservice deployment that is a ProxyPlatformAdapter whose set_presence publishes a presence action over the event bus for the Gateway to apply, which is how presence crosses the service boundary.

Constructed and owned by the inference service (inference_main.InferenceService), which calls start() once the event bus and discord proxy exist and stop() on shutdown. A leader_guard callable may gate the periodic loop so only one worker publishes presence. The message-processing path also injects this manager and calls set_status_from_tag() when the model emits an explicit status tag.

Parameters:
  • openrouter (Any)

  • discord_adapter (Any | None)

  • config (StatusConfig | None)

  • leader_guard (Any | None)

__init__(openrouter, discord_adapter=None, config=None, leader_guard=None)[source]

Initialize the instance.

Parameters:
  • openrouter (Any) – The openrouter value.

  • discord_adapter (Any | None) – The discord adapter value.

  • config (StatusConfig | None) – Bot configuration object.

  • leader_guard (Any | None) – Optional async callable returning True when this node should drive the periodic status loop. Used in the microservice deployment so only one worker generates/publishes presence (avoids flapping). When None the loop always runs (monolith / single-instance).

Return type:

None

start()[source]

Start the background presence loop if it is not already running.

Sets the running flag and schedules _loop() as a fire-and-forget asyncio task (stored on self._task) that periodically generates and publishes status updates; logs StatusManager started. Idempotent: returns immediately when a loop is already active. Invoked by inference_main.InferenceService after the event bus and discord proxy are wired up.

Return type:

None

stop()[source]

Signal the presence loop to stop and cancel its background task.

Clears the running flag and cancels the asyncio task created by start() (if any); does not await the cancellation. Safe to call when the loop was never started. Invoked by inference_main.InferenceService during service shutdown.

Return type:

None

async force_update()[source]

Run one status-generation/publish cycle immediately, off-schedule.

Bypasses the periodic timer by awaiting _cycle() directly, which may request a fresh LLM base status, rebuild the glitch variants, and push the next variant to Discord via the adapter. Intended for manual or test-driven refreshes; no production caller invokes it (exercised by the presence test suite).

Return type:

None

async set_status_from_tag(text)[source]

Override the presence with a model-supplied status string.

Used when the LLM emits an explicit status tag during a response: the raw text is stripped of any <thinking> block and surrounding quotes, clamped to config.max_length (truncating with an ellipsis if needed), then under self._status_lock it rebuilds the glitch-variant pool via _generate_variants(), resets the rotation cursor and base-update timestamp, and records the cleaned text as current_status. Finally pushes the cleaned text to Discord through _set_discord_status(). Called from the message-processing path (message_processor.generate_and_send and message_processor.channel_heartbeat).

Parameters:

text (str) – The raw status text emitted by the model.

Returns:

The cleaned, length-clamped status string that was applied.

Return type:

str

get_info()[source]

Return a small snapshot of the manager’s current state.

Reports the active status text, whether the background loop is running, and how many glitch variants are currently precomputed. A pure read with no side effects, intended for diagnostics and status surfaces; no in-repo caller invokes it directly.

Returns:

A mapping with current_status (str), is_running (bool), and num_variants (int).

Return type:

dict[str, Any]