Add server_type variable, gate fill/setblock/clone and template build on server_type=paper

This commit is contained in:
Claude Code
2026-03-16 19:36:12 -04:00
parent b7451e3290
commit cf2aeb1a5e
2 changed files with 49 additions and 5 deletions
+1
View File
@@ -1,5 +1,6 @@
{
"server_name": "paper-ai-25567",
"server_type": "paper",
"log_path": "/opt/paper-ai-25567/logs/latest.log",
"rcon_host": "127.0.0.1",
"rcon_port": 25577,
+48 -5
View File
@@ -767,6 +767,9 @@ def process_sudo_template_command(player: str, prompt: str, config) -> bool:
return True
if p.startswith("template build"):
if not get_server_capabilities(config).get("template_build", False):
_send_private(player, "[SUDO-TEMPLATE] template build requires a Paper server with WorldEdit/FAWE.", config, "yellow")
return True
rest = raw[len("template build"):].strip()
src = _resolve_template_file(rest, player, config)
if not src:
@@ -1214,6 +1217,38 @@ def get_player_context(player: str, config) -> str:
# LLM
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Server type capability sets
# ---------------------------------------------------------------------------
SERVER_CAPABILITIES = {
"vanilla": {
"safe_prefixes": [
'give ', 'effect ', 'xp ', 'tp ', 'time ', 'weather ',
'execute ', 'kill ', 'summon ', 'tellraw ', 'worldborder ',
],
"sudo_whitelist_note": "give, effect, xp, tp, time, weather, execute, kill, summon, tellraw, worldborder",
"template_build": False,
},
"paper": {
"safe_prefixes": [
'give ', 'effect ', 'xp ', 'tp ', 'time ', 'weather ',
'execute ', 'kill ', 'summon ', 'tellraw ', 'worldborder ',
'fill ', 'setblock ', 'clone ',
],
"sudo_whitelist_note": "give, effect, xp, tp, time, weather, execute, kill, summon, tellraw, worldborder, fill, setblock, clone",
"template_build": True,
},
}
DEFAULT_SERVER_TYPE = "paper"
def get_server_capabilities(config) -> dict:
server_type = str(config.get("server_type", DEFAULT_SERVER_TYPE)).lower().strip() if config else DEFAULT_SERVER_TYPE
return SERVER_CAPABILITIES.get(server_type, SERVER_CAPABILITIES[DEFAULT_SERVER_TYPE])
COMMAND_PALETTE = """
GIVE (any item, based on player need — see Item Naming Rules below):
SYNTAX: give <player> minecraft:<item_id> <count>
@@ -1445,13 +1480,16 @@ COMMANDS_SYSTEM_PROMPT = (
+ ENCHANTMENT_CONTEXT
)
SUDO_COMMANDS_SYSTEM_PROMPT = (
def build_sudo_commands_system_prompt(config=None) -> str:
caps = get_server_capabilities(config) if config else SERVER_CAPABILITIES[DEFAULT_SERVER_TYPE]
whitelist = caps["sudo_whitelist_note"]
return (
"You are a Minecraft command translator. Convert a player's natural-language request into "
"Minecraft server commands. You do NOT roleplay.\n\n"
"Respond ONLY with valid JSON:\n"
"{\"commands\": [\"cmd1\", \"cmd2\"]}\n\n"
"Rules:\n"
"- Use commands from this whitelist only: give, effect, xp, tp, time, weather, execute, kill, summon, tellraw, worldborder, fill, setblock, clone.\n"
f"- Use commands from this whitelist only: {whitelist}.\n"
"- If the request cannot be mapped safely, return commands: [].\n"
"- If player says 'me' or 'my', target the requesting player.\n"
"- You will receive LAST 10 SUDO ACTIONS. Use them for continuity and corrections when the player says previous output was wrong.\n"
@@ -1533,6 +1571,9 @@ FIRST_LOGIN_BENEVOLENCE_PROMPT = (
"- Use only whitelisted command families: give, effect, xp, tp, time, weather, execute, kill, summon, tellraw, worldborder.\n"
)
# Keep backward-compatible alias using default (paper) config
SUDO_COMMANDS_SYSTEM_PROMPT = build_sudo_commands_system_prompt()
def build_message_system_prompt(config) -> str:
base = (
"You are God in a Minecraft server. You are benevolent but just. "
@@ -2000,8 +2041,10 @@ def validate_command(cmd, online_players, fallback_player, config=None):
resolved = resolved[1:]
resolved = fix_give_command(resolved)
resolved = fix_effect_command(resolved)
if not any(resolved.startswith(p) for p in SAFE_PREFIXES):
log.warning(f"Command blocked (unknown prefix): {resolved}")
caps = get_server_capabilities(config) if config else SERVER_CAPABILITIES[DEFAULT_SERVER_TYPE]
prefixes = caps["safe_prefixes"]
if not any(resolved.startswith(p) for p in prefixes):
log.warning(f"Command blocked (unknown prefix for server_type={config.get('server_type', DEFAULT_SERVER_TYPE) if config else DEFAULT_SERVER_TYPE}): {resolved}")
return resolved, False
if config and _extract_tp_abs_xyz(resolved) and not _tp_inside_worldborder(resolved, config):
log.warning(f"Command blocked (tp outside worldborder): {resolved}")
@@ -2336,7 +2379,7 @@ def process_sudo(player, prompt, config):
def _local_sudo_translate() -> list:
content = _llm_call(
model=command_model,
system=SUDO_COMMANDS_SYSTEM_PROMPT,
system=build_sudo_commands_system_prompt(config),
user=context_hint,
config=config,
fmt="json",