Bump LLM Connect Init version to 0.7.8
Updated LLM Connect Init to v0.7.8 with new features including automatic API endpoint completion and enhanced context settings. Added functions for dynamic metadata handling and improved command collection. Signed-off-by: H5N3RG <janguenni13@web.de>
This commit is contained in:
140
init.lua
140
init.lua
@@ -1,10 +1,12 @@
|
|||||||
-- ===========================================================================
|
-- ===========================================================================
|
||||||
-- LLM Connect Init v0.7.7
|
-- LLM Connect Init v0.7.8
|
||||||
-- author: H5N3RG
|
-- author: H5N3RG
|
||||||
-- license: LGPL-3.0-or-later
|
-- license: LGPL-3.0-or-later
|
||||||
-- Fix: max_tokens type handling, fully configurable, robust JSON
|
-- Fix: max_tokens type handling, fully configurable, robust JSON
|
||||||
-- Added: metadata for ingame-commads
|
-- Added: metadata for ingame-commads
|
||||||
-- Enhancement: Dynamic metadata handling, player name in prompts
|
-- Enhancement: Dynamic metadata handling, player name in prompts
|
||||||
|
-- NEW: Automatic API endpoint completion for compatibility.
|
||||||
|
-- UPDATE: Configurable context sending
|
||||||
-- ===========================================================================
|
-- ===========================================================================
|
||||||
|
|
||||||
local core = core
|
local core = core
|
||||||
@@ -21,6 +23,50 @@ local api_key = core.settings:get("llm_api_key") or ""
|
|||||||
local api_url = core.settings:get("llm_api_url") or ""
|
local api_url = core.settings:get("llm_api_url") or ""
|
||||||
local model_name = core.settings:get("llm_model") or ""
|
local model_name = core.settings:get("llm_model") or ""
|
||||||
|
|
||||||
|
-- NEW Context Settings
|
||||||
|
local send_server_info = core.settings:get_bool("llm_context_send_server_info")
|
||||||
|
local send_mod_list = core.settings:get_bool("llm_context_send_mod_list")
|
||||||
|
local send_commands = core.settings:get_bool("llm_context_send_commands")
|
||||||
|
local send_player_pos = core.settings:get_bool("llm_context_send_player_pos")
|
||||||
|
local send_materials = core.settings:get_bool("llm_context_send_materials")
|
||||||
|
|
||||||
|
-- NEW: Function to check and complete the API endpoint
|
||||||
|
local function finalize_api_url(url)
|
||||||
|
if not url or url == "" then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 1. Remove trailing slash if present
|
||||||
|
local clean_url = url:gsub("/$", "")
|
||||||
|
|
||||||
|
-- Check if the URL contains a path component (everything after the host:port)
|
||||||
|
-- We assume any '/' after the protocol part (e.g., 'http://') or the host:port
|
||||||
|
-- indicates a user-defined path, which should not be overwritten.
|
||||||
|
-- Simple check: if the URL contains more than two slashes (e.g. 'http://host')
|
||||||
|
-- or if it contains any character after the host:port that is not part of the port number.
|
||||||
|
|
||||||
|
-- Attempt to find the end of the host/port part (first '/' after the protocol slashes)
|
||||||
|
local protocol_end = clean_url:find("://")
|
||||||
|
local host_end = 0
|
||||||
|
|
||||||
|
if protocol_end then
|
||||||
|
host_end = clean_url:find("/", protocol_end + 3) -- Find the first slash after '://'
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If no further slash is found (host_end is nil), it means only the base address (host:port) is present.
|
||||||
|
if not host_end then
|
||||||
|
-- Append the default OpenAI-compatible path
|
||||||
|
return clean_url .. "/v1/chat/completions"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If a path is found, use the URL as is.
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply the auto-completion/finalization logic
|
||||||
|
api_url = finalize_api_url(api_url)
|
||||||
|
|
||||||
|
|
||||||
-- max_tokens type: default integer, override via settings
|
-- max_tokens type: default integer, override via settings
|
||||||
local setting_val = core.settings:get_bool("llm_max_tokens_integer")
|
local setting_val = core.settings:get_bool("llm_max_tokens_integer")
|
||||||
local max_tokens_type = "integer"
|
local max_tokens_type = "integer"
|
||||||
@@ -87,16 +133,18 @@ local meta_data_functions = {}
|
|||||||
local function get_username(player_name) return player_name or "Unknown Player" end
|
local function get_username(player_name) return player_name or "Unknown Player" end
|
||||||
local function get_installed_mods()
|
local function get_installed_mods()
|
||||||
local mods = {}
|
local mods = {}
|
||||||
if core.get_mods then
|
-- NOTE: core.get_mods is undocumented. Using core.get_modnames (documented) instead.
|
||||||
for modname,_ in pairs(core.get_mods()) do table.insert(mods, modname) end
|
if core.get_modnames then
|
||||||
table.sort(mods)
|
-- core.get_modnames returns a table of mod names, already sorted alphabetically.
|
||||||
|
mods = core.get_modnames()
|
||||||
else
|
else
|
||||||
table.insert(mods,"Mod list not available")
|
-- Fallback for extremely old versions
|
||||||
|
table.insert(mods,"Mod list not available (core.get_modnames missing)")
|
||||||
end
|
end
|
||||||
return mods
|
return mods
|
||||||
end
|
end
|
||||||
|
|
||||||
-- NEUE FUNKTION: Befehle sammeln
|
-- Function to collect chat commands
|
||||||
local function get_installed_commands()
|
local function get_installed_commands()
|
||||||
local commands = {}
|
local commands = {}
|
||||||
if core.chatcommands then
|
if core.chatcommands then
|
||||||
@@ -131,7 +179,7 @@ function meta_data_functions.gather_context(player_name)
|
|||||||
local context = {}
|
local context = {}
|
||||||
context.player = get_username(player_name)
|
context.player = get_username(player_name)
|
||||||
context.installed_mods = get_installed_mods()
|
context.installed_mods = get_installed_mods()
|
||||||
context.installed_commands = get_installed_commands() -- HINZUGEFÜGT
|
context.installed_commands = get_installed_commands()
|
||||||
context.server_settings = get_server_settings()
|
context.server_settings = get_server_settings()
|
||||||
-- Add dynamic player data (e.g., position)
|
-- Add dynamic player data (e.g., position)
|
||||||
local player = core.get_player_by_name(player_name)
|
local player = core.get_player_by_name(player_name)
|
||||||
@@ -146,7 +194,13 @@ end
|
|||||||
|
|
||||||
-- Compute a simple hash for metadata to detect changes
|
-- Compute a simple hash for metadata to detect changes
|
||||||
local function compute_metadata_hash(context)
|
local function compute_metadata_hash(context)
|
||||||
local str = context.player .. context.server_settings.server_name .. context.server_settings.worldpath .. table.concat(context.installed_mods, ",") .. table.concat(context.installed_commands, ",") -- Hash aktualisiert
|
-- Hash calculation now depends on which fields are active to avoid unnecessary cache busts
|
||||||
|
local str = context.player
|
||||||
|
if send_server_info then str = str .. context.server_settings.server_name .. context.server_settings.worldpath end
|
||||||
|
if send_mod_list then str = str .. table.concat(context.installed_mods, ",") end
|
||||||
|
if send_commands then str = str .. table.concat(context.installed_commands, ",") end
|
||||||
|
if send_player_pos then str = str .. context.player_position end
|
||||||
|
-- Material context has its own hash in llm_materials_context.lua, so we don't include it here
|
||||||
return core.sha1(str)
|
return core.sha1(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -160,9 +214,9 @@ core.register_chatcommand("llm_setkey", {
|
|||||||
local parts = string_split(param," ")
|
local parts = string_split(param," ")
|
||||||
if #parts==0 then return false,"Please provide API key!" end
|
if #parts==0 then return false,"Please provide API key!" end
|
||||||
api_key = parts[1]
|
api_key = parts[1]
|
||||||
if parts[2] then api_url = parts[2] end
|
if parts[2] then api_url = finalize_api_url(parts[2]) end -- Apply finalization here too
|
||||||
if parts[3] then model_name = parts[3] end
|
if parts[3] then model_name = parts[3] end
|
||||||
core.chat_send_player(name,"[LLM] API key, URL and model set.")
|
core.chat_send_player(name,"[LLM] API key, URL and model set. (URL auto-corrected if only host:port was provided.)")
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@@ -187,8 +241,8 @@ core.register_chatcommand("llm_set_endpoint", {
|
|||||||
func = function(name,param)
|
func = function(name,param)
|
||||||
if not core.check_player_privs(name,{llm_root=true}) then return false,"No permission!" end
|
if not core.check_player_privs(name,{llm_root=true}) then return false,"No permission!" end
|
||||||
if param=="" then return false,"Provide URL!" end
|
if param=="" then return false,"Provide URL!" end
|
||||||
api_url = param
|
api_url = finalize_api_url(param) -- Apply finalization here
|
||||||
core.chat_send_player(name,"[LLM] API endpoint set to "..api_url)
|
core.chat_send_player(name,"[LLM] API endpoint set to "..api_url.." (URL auto-corrected if only host:port was provided.)")
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@@ -268,28 +322,47 @@ core.register_chatcommand("llm", {
|
|||||||
-- Build dynamic system prompt with metadata
|
-- Build dynamic system prompt with metadata
|
||||||
local dynamic_system_prompt = system_prompt_content
|
local dynamic_system_prompt = system_prompt_content
|
||||||
if needs_metadata_update then
|
if needs_metadata_update then
|
||||||
local mods_list_str = table.concat(context_data.installed_mods,", ")
|
|
||||||
if #context_data.installed_mods>10 then mods_list_str="(More than 10 installed mods: "..#context_data.installed_mods..")" end
|
|
||||||
local materials_context_str = ""
|
|
||||||
if llm_materials_context and llm_materials_context.get_available_materials then
|
|
||||||
materials_context_str = "\n\n--- AVAILABLE MATERIALS ---\n" .. llm_materials_context.get_available_materials()
|
|
||||||
end
|
|
||||||
-- Befehlsliste hinzufügen
|
|
||||||
local commands_list_str = table.concat(context_data.installed_commands, "\n")
|
|
||||||
|
|
||||||
local metadata_string = "\n\n--- METADATA ---\n" ..
|
local metadata_string = "\n\n--- METADATA ---\n" ..
|
||||||
"Player: " .. context_data.player .. "\n" ..
|
"Player: " .. context_data.player .. "\n"
|
||||||
"Player Position: " .. context_data.player_position .. "\n" ..
|
|
||||||
"Server Name: " .. context_data.server_settings.server_name .. "\n" ..
|
-- Conditional Player Position
|
||||||
"Server Description: " .. context_data.server_settings.server_description .. "\n" ..
|
if send_player_pos then
|
||||||
"MOTD: " .. context_data.server_settings.motd .. "\n" ..
|
metadata_string = metadata_string .. "Player Position: " .. context_data.player_position .. "\n"
|
||||||
"Game: " .. context_data.server_settings.game_name .. " (" .. context_data.server_settings.gameid .. ")\n" ..
|
end
|
||||||
"Mapgen: " .. context_data.server_settings.mapgen .. "\n" ..
|
|
||||||
"World Path: " .. context_data.server_settings.worldpath .. "\n" ..
|
-- Conditional Server Info
|
||||||
"Port: " .. context_data.server_settings.port .. "\n" ..
|
if send_server_info then
|
||||||
"Installed Mods (" .. #context_data.installed_mods .. "): " .. mods_list_str .. "\n" ..
|
metadata_string = metadata_string ..
|
||||||
"Available Commands:\n" .. commands_list_str .. "\n" .. -- HINZUGEFÜGT
|
"Server Name: " .. context_data.server_settings.server_name .. "\n" ..
|
||||||
materials_context_str
|
"Server Description: " .. context_data.server_settings.server_description .. "\n" ..
|
||||||
|
"MOTD: " .. context_data.server_settings.motd .. "\n" ..
|
||||||
|
"Game: " .. context_data.server_settings.game_name .. " (" .. context_data.server_settings.gameid .. ")\n" ..
|
||||||
|
"Mapgen: " .. context_data.server_settings.mapgen .. "\n" ..
|
||||||
|
"World Path: " .. context_data.server_settings.worldpath .. "\n" ..
|
||||||
|
"Port: " .. context_data.server_settings.port .. "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Conditional Mod List
|
||||||
|
if send_mod_list then
|
||||||
|
local mods_list_str = table.concat(context_data.installed_mods,", ")
|
||||||
|
if #context_data.installed_mods>10 then mods_list_str="(More than 10 installed mods: "..#context_data.installed_mods..")" end
|
||||||
|
metadata_string = metadata_string ..
|
||||||
|
"Installed Mods (" .. #context_data.installed_mods .. "): " .. mods_list_str .. "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Conditional Command List
|
||||||
|
if send_commands then
|
||||||
|
local commands_list_str = table.concat(context_data.installed_commands, "\n")
|
||||||
|
metadata_string = metadata_string ..
|
||||||
|
"Available Commands:\n" .. commands_list_str .. "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Conditional Materials Context
|
||||||
|
if send_materials and llm_materials_context and llm_materials_context.get_available_materials then
|
||||||
|
metadata_string = metadata_string ..
|
||||||
|
"\n--- AVAILABLE MATERIALS ---\n" .. llm_materials_context.get_available_materials()
|
||||||
|
end
|
||||||
|
|
||||||
dynamic_system_prompt = system_prompt_content .. metadata_string
|
dynamic_system_prompt = system_prompt_content .. metadata_string
|
||||||
metadata_cache[name] = { hash = current_metadata_hash, metadata = metadata_string }
|
metadata_cache[name] = { hash = current_metadata_hash, metadata = metadata_string }
|
||||||
else
|
else
|
||||||
@@ -316,6 +389,7 @@ core.register_chatcommand("llm", {
|
|||||||
|
|
||||||
core.log("action", "[llm_connect DEBUG] max_tokens_type = " .. max_tokens_type)
|
core.log("action", "[llm_connect DEBUG] max_tokens_type = " .. max_tokens_type)
|
||||||
core.log("action", "[llm_connect DEBUG] max_tokens_value = " .. tostring(max_tokens_value))
|
core.log("action", "[llm_connect DEBUG] max_tokens_value = " .. tostring(max_tokens_value))
|
||||||
|
core.log("action", "[llm_connect DEBUG] API URL used: " .. api_url) -- Log the final URL
|
||||||
|
|
||||||
-- Send HTTP request
|
-- Send HTTP request
|
||||||
http.fetch({
|
http.fetch({
|
||||||
|
|||||||
Reference in New Issue
Block a user