From a70e94210add2515891d4a5a987fee5373e6501a Mon Sep 17 00:00:00 2001 From: KyuYeon Lee Date: Thu, 14 Aug 2025 21:50:38 +0900 Subject: [PATCH 1/4] feat: support Grok-4 by adding x.ai API category (xai) --- lua/gp/config.lua | 14 ++++++++++++ lua/gp/dispatcher.lua | 51 ++++++++++++++++++++----------------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/lua/gp/config.lua b/lua/gp/config.lua index 22d2ce8..8a6f0b0 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -72,6 +72,11 @@ local config = { endpoint = "https://api.anthropic.com/v1/messages", secret = os.getenv("ANTHROPIC_API_KEY"), }, + xai = { + disable = true, + endpoint = "https://api.x.ai/v1/chat/completions", + secret = os.getenv("XAI_API_KEY"), + }, }, -- prefix for all commands @@ -310,6 +315,15 @@ local config = { model = { model = "claude-3-5-haiku-latest", temperature = 0.8, top_p = 1 }, system_prompt = require("gp.defaults").code_system_prompt, }, + { + provider = "xai", + name = "Grok-4", + chat = false, + command = true, + -- string with model name or table with model name and parameters + model = { model = "grok-4-latest", temperature = 0 }, + system_prompt = require("gp.defaults").code_system_prompt, + }, { provider = "ollama", name = "CodeOllamaLlama3.1-8B", diff --git a/lua/gp/dispatcher.lua b/lua/gp/dispatcher.lua index c28caba..d3d6208 100644 --- a/lua/gp/dispatcher.lua +++ b/lua/gp/dispatcher.lua @@ -169,38 +169,27 @@ D.prepare_payload = function(messages, model, provider) return payload end - if provider == "ollama" then + if provider == "xai" then + local system = "" + local i = 1 + while i < #messages do + if messages[i].role == "system" then + system = system .. messages[i].content .. "\n" + table.remove(messages, i) + else + i = i + 1 + end + end + local payload = { model = model.model, stream = true, messages = messages, + system = system, + max_tokens = model.max_tokens or 4096, + temperature = math.max(0, math.min(2, model.temperature or 1)), + top_p = math.max(0, math.min(1, model.top_p or 1)), } - - if model.think ~= nil then - payload.think = model.think - end - - local options = {} - if model.temperature then - options.temperature = math.max(0, math.min(2, model.temperature)) - end - if model.top_p then - options.top_p = math.max(0, math.min(1, model.top_p)) - end - if model.min_p then - options.min_p = math.max(0, math.min(1, model.min_p)) - end - if model.num_ctx then - options.num_ctx = model.num_ctx - end - if model.top_k then - options.top_k = model.top_k - end - - if next(options) then - payload.options = options - end - return payload end @@ -454,6 +443,14 @@ local query = function(buf, provider, payload, handler, on_exit, callback) endpoint = render.template_replace(endpoint, "{{model}}", payload.model) elseif provider == "ollama" then headers = {} + elseif provider == "xai" then + -- currently xai only uses bearer token for authentication. + -- since I cannot sure its going to be that way for long time + -- branching out as another condition. + headers = { + "-H", + "Authorization: Bearer " .. bearer, + } else -- default to openai compatible headers headers = { "-H", From b4d54d0de5f51e405e47c89c4cc6bfd9e99cbac6 Mon Sep 17 00:00:00 2001 From: KyuYeon Lee Date: Thu, 14 Aug 2025 21:53:41 +0900 Subject: [PATCH 2/4] fix: bring back unwanted changes --- lua/gp/dispatcher.lua | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/lua/gp/dispatcher.lua b/lua/gp/dispatcher.lua index d3d6208..725d0df 100644 --- a/lua/gp/dispatcher.lua +++ b/lua/gp/dispatcher.lua @@ -193,6 +193,41 @@ D.prepare_payload = function(messages, model, provider) return payload end + if provider == "ollama" then + local payload = { + model = model.model, + stream = true, + messages = messages, + } + + if model.think ~= nil then + payload.think = model.think + end + + local options = {} + if model.temperature then + options.temperature = math.max(0, math.min(2, model.temperature)) + end + if model.top_p then + options.top_p = math.max(0, math.min(1, model.top_p)) + end + if model.min_p then + options.min_p = math.max(0, math.min(1, model.min_p)) + end + if model.num_ctx then + options.num_ctx = model.num_ctx + end + if model.top_k then + options.top_k = model.top_k + end + + if next(options) then + payload.options = options + end + + return payload + end + local output = { model = model.model, stream = true, From 32bd421226b16bad7dd68419e6bfcb98b4b43848 Mon Sep 17 00:00:00 2001 From: KyuYeon Lee Date: Thu, 14 Aug 2025 21:54:56 +0900 Subject: [PATCH 3/4] chore: change the order of authentication provider --- lua/gp/dispatcher.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/gp/dispatcher.lua b/lua/gp/dispatcher.lua index 725d0df..b5f4b71 100644 --- a/lua/gp/dispatcher.lua +++ b/lua/gp/dispatcher.lua @@ -476,8 +476,6 @@ local query = function(buf, provider, payload, handler, on_exit, callback) "api-key: " .. bearer, } endpoint = render.template_replace(endpoint, "{{model}}", payload.model) - elseif provider == "ollama" then - headers = {} elseif provider == "xai" then -- currently xai only uses bearer token for authentication. -- since I cannot sure its going to be that way for long time @@ -486,6 +484,8 @@ local query = function(buf, provider, payload, handler, on_exit, callback) "-H", "Authorization: Bearer " .. bearer, } + elseif provider == "ollama" then + headers = {} else -- default to openai compatible headers headers = { "-H", From 6af90ba3db9b4f6ff18fcce64c138fb7403c2682 Mon Sep 17 00:00:00 2001 From: KyuYeon Lee Date: Fri, 15 Aug 2025 09:35:52 +0900 Subject: [PATCH 4/4] chore: Added information about Grok-4 and x.ai in README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index b69b4b9..89e1cd0 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ The following LLM providers are currently supported besides OpenAI: - [Perplexity.ai](https://www.perplexity.ai/pro) Pro users have $5/month free API credits available (the default PPLX agent uses Mixtral-8x7b). - [Anthropic](https://www.anthropic.com/api) to access Claude models, which currently outperform GPT-4 in some benchmarks. - [Google Gemini](https://ai.google.dev/) with a quite generous free range but some geo-restrictions (EU). +- [x.ai](https://x.ai/api) to access Grok-4 with pre-paid credit plans (No free credit available at this moment). - Any other "OpenAI chat/completions" compatible endpoint (Azure, LM Studio, etc.) Below is an example of the relevant configuration part enabling some of these. The `secret` field has the same capabilities as `openai_api_key` (which is still supported for compatibility). @@ -171,6 +172,11 @@ Below is an example of the relevant configuration part enabling some of these. T endpoint = "https://api.anthropic.com/v1/messages", secret = os.getenv("ANTHROPIC_API_KEY"), }, + + xai = { + endpoint = "https://api.x.ai/v1/chat/completions", + secret = os.getenv("XAI_API_KEY"), + }, }, ```