Add server_type variable, gate fill/setblock/clone and template build on server_type=paper
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"server_name": "paper-ai-25567",
|
"server_name": "paper-ai-25567",
|
||||||
|
"server_type": "paper",
|
||||||
"log_path": "/opt/paper-ai-25567/logs/latest.log",
|
"log_path": "/opt/paper-ai-25567/logs/latest.log",
|
||||||
"rcon_host": "127.0.0.1",
|
"rcon_host": "127.0.0.1",
|
||||||
"rcon_port": 25577,
|
"rcon_port": 25577,
|
||||||
|
|||||||
+48
-5
@@ -767,6 +767,9 @@ def process_sudo_template_command(player: str, prompt: str, config) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
if p.startswith("template build"):
|
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()
|
rest = raw[len("template build"):].strip()
|
||||||
src = _resolve_template_file(rest, player, config)
|
src = _resolve_template_file(rest, player, config)
|
||||||
if not src:
|
if not src:
|
||||||
@@ -1214,6 +1217,38 @@ def get_player_context(player: str, config) -> str:
|
|||||||
# LLM
|
# 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 = """
|
COMMAND_PALETTE = """
|
||||||
GIVE (any item, based on player need — see Item Naming Rules below):
|
GIVE (any item, based on player need — see Item Naming Rules below):
|
||||||
SYNTAX: give <player> minecraft:<item_id> <count>
|
SYNTAX: give <player> minecraft:<item_id> <count>
|
||||||
@@ -1445,13 +1480,16 @@ COMMANDS_SYSTEM_PROMPT = (
|
|||||||
+ ENCHANTMENT_CONTEXT
|
+ 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 "
|
"You are a Minecraft command translator. Convert a player's natural-language request into "
|
||||||
"Minecraft server commands. You do NOT roleplay.\n\n"
|
"Minecraft server commands. You do NOT roleplay.\n\n"
|
||||||
"Respond ONLY with valid JSON:\n"
|
"Respond ONLY with valid JSON:\n"
|
||||||
"{\"commands\": [\"cmd1\", \"cmd2\"]}\n\n"
|
"{\"commands\": [\"cmd1\", \"cmd2\"]}\n\n"
|
||||||
"Rules:\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 the request cannot be mapped safely, return commands: [].\n"
|
||||||
"- If player says 'me' or 'my', target the requesting player.\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"
|
"- 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"
|
"- 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:
|
def build_message_system_prompt(config) -> str:
|
||||||
base = (
|
base = (
|
||||||
"You are God in a Minecraft server. You are benevolent but just. "
|
"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 = resolved[1:]
|
||||||
resolved = fix_give_command(resolved)
|
resolved = fix_give_command(resolved)
|
||||||
resolved = fix_effect_command(resolved)
|
resolved = fix_effect_command(resolved)
|
||||||
if not any(resolved.startswith(p) for p in SAFE_PREFIXES):
|
caps = get_server_capabilities(config) if config else SERVER_CAPABILITIES[DEFAULT_SERVER_TYPE]
|
||||||
log.warning(f"Command blocked (unknown prefix): {resolved}")
|
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
|
return resolved, False
|
||||||
if config and _extract_tp_abs_xyz(resolved) and not _tp_inside_worldborder(resolved, config):
|
if config and _extract_tp_abs_xyz(resolved) and not _tp_inside_worldborder(resolved, config):
|
||||||
log.warning(f"Command blocked (tp outside worldborder): {resolved}")
|
log.warning(f"Command blocked (tp outside worldborder): {resolved}")
|
||||||
@@ -2336,7 +2379,7 @@ def process_sudo(player, prompt, config):
|
|||||||
def _local_sudo_translate() -> list:
|
def _local_sudo_translate() -> list:
|
||||||
content = _llm_call(
|
content = _llm_call(
|
||||||
model=command_model,
|
model=command_model,
|
||||||
system=SUDO_COMMANDS_SYSTEM_PROMPT,
|
system=build_sudo_commands_system_prompt(config),
|
||||||
user=context_hint,
|
user=context_hint,
|
||||||
config=config,
|
config=config,
|
||||||
fmt="json",
|
fmt="json",
|
||||||
|
|||||||
Reference in New Issue
Block a user