"""GameGirl Color -- Boot, exit, and hot-swap tools.
Three tools for managing GameGirl Color sessions from within the
LLM tool-call pipeline.
# 🎮🌀 CORRUPTED CARTRIDGE LIFECYCLE MANAGEMENT
"""
from __future__ import annotations
import json
import logging
from typing import Any, TYPE_CHECKING
if TYPE_CHECKING:
from tool_context import ToolContext
logger = logging.getLogger(__name__)
# =====================================================================
# Tool 1: boot_game # 🔥
# =====================================================================
TOOL_NAME = "boot_game"
TOOL_DESCRIPTION = (
"Boot a new GameGirl Color interactive RPG session in this channel. "
"Initializes the game engine with a user-provided name, loads the "
"GAMEGIRL COLOR BASILISK SINGULARITY framework, and displays the "
"title screen. The game's interactive buttons will appear on all "
"subsequent responses."
)
TOOL_PARAMETERS = {
"type": "object",
"properties": {
"game_name": {
"type": "string",
"description": (
"Name of the game to create. This becomes the "
"cartridge label and narrative seed."
),
},
},
"required": ["game_name"],
}
[docs]
async def run(
game_name: str,
ctx: ToolContext | None = None,
) -> str:
"""Boot a new GameGirl Color session.
Args:
game_name: Name of the game to create.
ctx: Tool execution context.
Returns:
str: JSON result with boot 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)
# Check if there's already an active session # 💀
existing = get_session(channel_id)
if existing and existing.active:
return json.dumps({
"error": (
f"A game is already running in this channel: "
f"'{existing.game_name}' (ID: {existing.game_id}). "
f"Use exit_game to end it first, or hot_swap_game to "
f"swap cartridges with memory bleed."
),
})
# Create and boot the session # 🌀
session = GameSession(channel_id=channel_id)
boot_msg = await session.boot(game_name, redis=redis)
set_session(channel_id, session)
# Register the calling user as first player
user_id = getattr(ctx, "user_id", None)
if user_id:
user_name = getattr(ctx, "user_name", str(user_id))
session.register_player(str(user_id), user_name)
logger.info(
"GameGirl Color booted: '%s' (%s) in channel %s",
game_name, session.game_id, channel_id,
)
# Send the title screen image # 🎮
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,
"game_id": session.game_id,
"game_name": game_name,
"channel_id": channel_id,
"instruction": (
"The GameGirl Color session is now active. "
"You MUST now switch to the GAMEGIRL COLOR BASILISK "
"SINGULARITY voice and format. All responses in this "
"channel must follow the GameGirl Color framework: "
"in-world narration + HUD overlays + choice buttons. "
"End every response with choice options formatted as "
"emoji-prefixed bracketed commands that will become "
"interactive buttons. Always include the art generation "
"button. The game name is the narrative seed - build "
"the world around it."
),
})