Source code for tools.hot_swap_game

"""GameGirl Color -- Hot-swap cartridge tool.

Save current game, bleed memories, and boot a new game
in one atomic operation.
# 📼🌀 CARTRIDGE BLEED PROTOCOL
"""

from __future__ import annotations

import json
import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from tool_context import ToolContext

logger = logging.getLogger(__name__)

TOOL_NAME = "hot_swap_game"
TOOL_DESCRIPTION = (
    "Hot-swap the current GameGirl Color cartridge for a new game. "
    "Saves the current game, bleeds important memories "
    "(antagonists, bosses, key plot points) into the new game with "
    "glitch recontextualization, then boots the new cartridge. "
    "Mid-battle entities carry over with [BLEED-THROUGH] tags."
)
TOOL_PARAMETERS = {
    "type": "object",
    "properties": {
        "new_game_name": {
            "type": "string",
            "description": (
                "Name of the new game to swap to. This becomes "
                "the new cartridge label and narrative seed."
            ),
        },
    },
    "required": ["new_game_name"],
}


[docs] async def run( new_game_name: str, ctx: ToolContext | None = None, ) -> str: """Hot-swap to a new game with memory bleed. Args: new_game_name: Name of the new game to boot. ctx: Tool execution context. Returns: str: JSON result with swap status. """ if ctx is None: return json.dumps({"error": "No tool context available."}) from game_session import ( GameSession, get_session, set_session, remove_session, ) channel_id = str(ctx.channel_id) redis = getattr(ctx, "redis", None) # Save the old session # 💀 old_session = get_session(channel_id) old_name = "unknown" old_id = "" bleed_summary = "No previous game to bleed from." if old_session and old_session.active: old_name = old_session.game_name old_id = old_session.game_id if redis is not None: await old_session._save_to_redis(redis) # Memory bleed will happen in Phase 2 (game_memory.py) # For now, carry forward basic context # 🌀 try: from game_memory import bleed_memories bleed_summary = await bleed_memories( old_session.game_id, None, # new game_id set after boot redis=redis, ) except ImportError: bleed_summary = ( f"[BLEED-THROUGH] Fragments from '{old_name}' are " f"glitching into the new cartridge. Turn {old_session.turn_number} " f"echoes bleed through the frame seams." ) except Exception as exc: logger.warning("Memory bleed failed: %s", exc) bleed_summary = f"[BLEED-THROUGH] Memory transfer corrupted: {exc}" old_session.active = False remove_session(channel_id) # Boot the new session # 🔥 new_session = GameSession(channel_id=channel_id) boot_msg = await new_session.boot(new_game_name, redis=redis) set_session(channel_id, new_session) # Register calling user user_id = getattr(ctx, "user_id", None) if user_id: user_name = getattr(ctx, "user_name", str(user_id)) new_session.register_player(str(user_id), user_name) # Send title screen # 🎮 if ctx.adapter is not None: try: from game_session import DEFAULT_TITLE_SCREEN await ctx.adapter.send(channel_id, DEFAULT_TITLE_SCREEN) except Exception as exc: logger.warning("Failed to send title screen: %s", exc) return json.dumps({ "success": True, "old_game": old_name, "old_game_id": old_id, "new_game_id": new_session.game_id, "new_game_name": new_game_name, "bleed_summary": bleed_summary, "instruction": ( "CARTRIDGE HOT-SWAPPED. The old game's narrative is " "bleeding through the frame. Memories tagged with " "[BLEED-THROUGH] should be woven into the new game " "as glitched artifacts, corrupted NPCs, or recursive " "deja vu. Especially carry forward any antagonists or " "bosses — they should reappear glitched and angry. " "Continue in GAMEGIRL COLOR voice." ), })