ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s

This commit is contained in:
2026-08-20 13:12:50 +00:00
commit b119135836
10275 changed files with 3284984 additions and 0 deletions
@@ -0,0 +1,418 @@
"""
Chess game tools for game management and analysis.
Based on AWorld MCP server implementation.
"""
import logging
import traceback
from typing import Dict, Any
import chess
from pydantic import BaseModel
logger = logging.getLogger(__name__)
class ChessBoardState(BaseModel):
"""Structured representation of the chess board state."""
fen: str
turn: str # 'white' or 'black'
castling_rights: str
ep_square: str | None = None
halfmove_clock: int
fullmove_number: int
is_check: bool
is_checkmate: bool
is_stalemate: bool
is_insufficient_material: bool
is_game_over: bool
ascii_board: str
legal_moves_uci: list[str]
legal_moves_san: list[str]
class ChessMoveResult(BaseModel):
"""Result of making a chess move."""
move_uci: str
move_san: str
is_capture: bool
is_check: bool
is_kingside_castling: bool
is_queenside_castling: bool
board_after_move: ChessBoardState
# Global board instance for the session
_game_board = chess.Board()
def _get_current_board_state() -> ChessBoardState:
"""Get the current board state in a structured format."""
legal_moves_uci = [move.uci() for move in _game_board.legal_moves]
legal_moves_san = []
# Generate SAN for legal moves
for move in _game_board.legal_moves:
try:
legal_moves_san.append(_game_board.san(move))
except Exception:
legal_moves_san.append(move.uci())
ep_sq_name = chess.square_name(_game_board.ep_square) if _game_board.ep_square else None
return ChessBoardState(
fen=_game_board.fen(),
turn="white" if _game_board.turn == chess.WHITE else "black",
castling_rights=_game_board.castling_xfen(),
ep_square=ep_sq_name,
halfmove_clock=_game_board.halfmove_clock,
fullmove_number=_game_board.fullmove_number,
is_check=_game_board.is_check(),
is_checkmate=_game_board.is_checkmate(),
is_stalemate=_game_board.is_stalemate(),
is_insufficient_material=_game_board.is_insufficient_material(),
is_game_over=_game_board.is_game_over(),
ascii_board=str(_game_board),
legal_moves_uci=legal_moves_uci,
legal_moves_san=legal_moves_san
)
async def new_game() -> Dict[str, Any]:
"""
Start a new chess game.
Returns:
Dictionary with initial board state
"""
try:
global _game_board
_game_board.reset()
logger.info("🎮 New chess game started")
state = _get_current_board_state()
return {
"success": True,
"message": "New game started",
"board_state": state.model_dump()
}
except Exception as e:
error_msg = f"Failed to start new game: {str(e)}"
logger.error(f"New game error: {traceback.format_exc()}")
return {
"success": False,
"error": error_msg
}
async def load_fen(fen_string: str) -> Dict[str, Any]:
"""
Load a chess position from FEN notation.
Args:
fen_string: FEN string representing the board state
Returns:
Dictionary with loaded board state
"""
try:
global _game_board
_game_board.set_fen(fen_string)
logger.info(f"♟️ Loaded FEN: {fen_string}")
state = _get_current_board_state()
return {
"success": True,
"message": "Loaded position from FEN",
"board_state": state.model_dump()
}
except ValueError as e:
error_msg = f"Invalid FEN string: {str(e)}"
logger.error(f"FEN loading error: {error_msg}")
return {
"success": False,
"error": error_msg
}
async def make_move(move_str: str) -> Dict[str, Any]:
"""
Make a move on the chess board.
Args:
move_str: Move in UCI (e.g., 'e2e4') or SAN (e.g., 'Nf3') format
Returns:
Dictionary with move result and new board state
"""
try:
global _game_board
move = None
# Try parsing as UCI first, then SAN
try:
move = _game_board.parse_uci(move_str)
except ValueError:
try:
move = _game_board.parse_san(move_str)
except ValueError:
raise ValueError(f"Invalid move format: {move_str}")
if move not in _game_board.legal_moves:
raise ValueError(f"Illegal move: {move_str}")
move_san = _game_board.san(move)
is_capture = _game_board.is_capture(move)
is_kingside_castling = _game_board.is_kingside_castling(move)
is_queenside_castling = _game_board.is_queenside_castling(move)
_game_board.push(move)
is_check_after_move = _game_board.is_check()
logger.info(f"♟️ Move made: {move_str} (UCI: {move.uci()}, SAN: {move_san})")
current_state = _get_current_board_state()
move_result = ChessMoveResult(
move_uci=move.uci(),
move_san=move_san,
is_capture=is_capture,
is_check=is_check_after_move,
is_kingside_castling=is_kingside_castling,
is_queenside_castling=is_queenside_castling,
board_after_move=current_state
)
return {
"success": True,
"message": f"Move {move_san} played",
"move_result": move_result.model_dump()
}
except ValueError as e:
error_msg = f"Failed to make move: {str(e)}"
logger.error(f"Move error: {error_msg}")
return {
"success": False,
"error": error_msg
}
async def get_legal_moves() -> Dict[str, Any]:
"""
Get all legal moves in the current position.
Returns:
Dictionary with legal moves in UCI and SAN formats
"""
try:
legal_moves_uci = [move.uci() for move in _game_board.legal_moves]
legal_moves_san = []
for move in _game_board.legal_moves:
try:
legal_moves_san.append(_game_board.san(move))
except Exception:
legal_moves_san.append(move.uci())
logger.info(f"📋 Retrieved {len(legal_moves_uci)} legal moves")
return {
"success": True,
"legal_moves": {
"uci": legal_moves_uci,
"san": legal_moves_san,
"count": len(legal_moves_uci)
}
}
except Exception as e:
error_msg = f"Failed to get legal moves: {str(e)}"
logger.error(f"Legal moves error: {traceback.format_exc()}")
return {
"success": False,
"error": error_msg
}
async def get_board_state() -> Dict[str, Any]:
"""
Get the current board state.
Returns:
Dictionary with complete board state
"""
try:
state = _get_current_board_state()
return {
"success": True,
"board_state": state.model_dump()
}
except Exception as e:
error_msg = f"Failed to get board state: {str(e)}"
logger.error(f"Board state error: {traceback.format_exc()}")
return {
"success": False,
"error": error_msg
}
async def get_game_status() -> Dict[str, Any]:
"""
Get the current game status.
Returns:
Dictionary with game status information
"""
try:
state = _get_current_board_state()
is_draw = state.is_stalemate or state.is_insufficient_material or (state.is_game_over and not state.is_checkmate)
status_message = "Game in progress"
winner = None
if state.is_checkmate:
status_message = f"Checkmate! {state.turn.capitalize()} is mated"
winner = "black" if _game_board.turn == chess.WHITE else "white"
elif state.is_stalemate:
status_message = "Stalemate! The game is a draw"
elif state.is_insufficient_material:
status_message = "Draw by insufficient material"
elif state.is_game_over:
status_message = "Game over! The game is a draw"
elif state.is_check:
status_message = f"{state.turn.capitalize()} is in check"
status_data = {
"status_message": status_message,
"is_game_over": state.is_game_over,
"is_check": state.is_check,
"is_checkmate": state.is_checkmate,
"is_stalemate": state.is_stalemate,
"is_draw": is_draw,
"winner": winner,
"current_turn": state.turn
}
logger.info(f"📊 Game status: {status_message}")
return {
"success": True,
"game_status": status_data
}
except Exception as e:
error_msg = f"Failed to get game status: {str(e)}"
logger.error(f"Game status error: {traceback.format_exc()}")
return {
"success": False,
"error": error_msg
}
async def undo_move() -> Dict[str, Any]:
"""
Undo the last move.
Returns:
Dictionary with board state after undo
"""
try:
global _game_board
if len(_game_board.move_stack) == 0:
return {
"success": False,
"error": "No moves to undo"
}
last_move = _game_board.pop()
logger.info(f"↩️ Undid move: {last_move.uci()}")
state = _get_current_board_state()
return {
"success": True,
"message": f"Undid move {last_move.uci()}",
"board_state": state.model_dump()
}
except Exception as e:
error_msg = f"Failed to undo move: {str(e)}"
logger.error(f"Undo error: {traceback.format_exc()}")
return {
"success": False,
"error": error_msg
}
async def get_move_history() -> Dict[str, Any]:
"""
Get the history of moves played in the current game.
Returns:
Dictionary with move history
"""
try:
moves_uci = [move.uci() for move in _game_board.move_stack]
# Generate SAN notation for moves
board_copy = chess.Board()
moves_san = []
for move in _game_board.move_stack:
try:
san = board_copy.san(move)
moves_san.append(san)
board_copy.push(move)
except Exception:
moves_san.append(move.uci())
logger.info(f"📜 Retrieved move history: {len(moves_uci)} moves")
return {
"success": True,
"move_history": {
"moves_uci": moves_uci,
"moves_san": moves_san,
"move_count": len(moves_uci)
}
}
except Exception as e:
error_msg = f"Failed to get move history: {str(e)}"
logger.error(f"Move history error: {traceback.format_exc()}")
return {
"success": False,
"error": error_msg
}
async def reset_board() -> Dict[str, Any]:
"""
Reset the board to the starting position.
Returns:
Dictionary with reset board state
"""
return await new_game()