Skip to content

Commit ca38022

Browse files
Release v0.1.1: UI Polish and Bug Fixes
Release v0.1.1: UI Polish and Bug Fixes
2 parents 40a84b4 + 0fe7119 commit ca38022

File tree

15 files changed

+939
-98
lines changed

15 files changed

+939
-98
lines changed

issue_tracker.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,26 @@
4040
- Add config location for prompt box (3 settings, left, center, right)
4141
- Clean up UI/UX and ensure user prompt scales with the users typing.
4242

43+
## Issue 5: Inconsistent Prompt Box Display** (Target: 0.1.2)
44+
- Problem: Prompt box only displays properly on first :Grok; reverts to old style after.
45+
- Analysis: Likely state issue in chat/init.lua or ui/window.lua; floating input not reinitialized.
46+
- Solution: Ensure util.create_floating_input called consistently on each prompt.
47+
- Status: [ ] Not implemented.
4348

49+
## Issue 6: Verify Max Prompt Length for Models** (Target: 0.1.1)
50+
- Problem: Current max 131072 for Grok-3-mini; confirm accuracy.
51+
- Analysis: From x.ai docs, Grok-3-mini context window is 131072 tokens (confirmed).
52+
- Solution: Update util.get_model_max_tokens with verified values; add more models.
53+
- Status: [] Verified (131072 tokens); implement dynamic if API provides.
54+
55+
## Issue 7: Grok Prevents Smooth Neovim Exit** (Target: 0.1.2)
56+
- Problem: Requires :qa! to exit Neovim after using Grok.
57+
- Analysis: Likely unclosed buffers/windows or autocmds; check ui/window.lua close logic.
58+
- Solution: Ensure close_chat_window cleans up properly; add vim.api.nvim_buf_delete on exit.
59+
- Status: [ ] Not implemented.
60+
61+
## Issue 8: Expand and Modularize Logging (Target: v0.1.3)
62+
- **Problem:** Debug logs print regardless of config.debug setting, hurting performance; logging is monolithic in single core.lua file.
63+
- **Analysis:** v0.1.1 util.lua introduced debug_log() concept but inconsistent across project; log/core.lua handles everything (levels, rotation, debug) without modularity.
64+
- **Solution:** Modularize into log/log.lua (main), log/logger.lua (debug wrapper), log/rotate.lua (file management); enforce config.debug gate on ALL debug logs project-wide for 35%+ performance gain.
65+
- **Status:** [ ] Not implemented.

lua/grok/chat/history.lua

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,50 @@
11
-- ~/github.com/acris-software/grok-nvim/lua/grok/chat/history.lua
2-
32
local M = {}
43

4+
local history_file = vim.fn.stdpath("data") .. "/grok_chat_history.json"
55
M.history = {}
66

7+
function M.load()
8+
local file = io.open(history_file, "r")
9+
if file then
10+
local content = file:read("*a")
11+
file:close()
12+
if content and content ~= "" then
13+
local ok, loaded_history = pcall(vim.json.decode, content)
14+
if ok and type(loaded_history) == "table" then
15+
M.history = loaded_history
16+
end
17+
end
18+
end
19+
end
20+
21+
function M.save()
22+
local file = io.open(history_file, "w")
23+
if file then
24+
file:write(vim.json.encode(M.history))
25+
file:close()
26+
end
27+
end
28+
729
function M.add(role, content)
830
table.insert(M.history, { role = role, content = content })
31+
-- Limit history to 10 messages to prevent excessive growth
32+
if #M.history > 10 then
33+
table.remove(M.history, 1)
34+
end
35+
M.save()
936
end
1037

1138
function M.get()
39+
if #M.history == 0 then
40+
M.load()
41+
end
1242
return M.history
1343
end
1444

1545
function M.clear()
1646
M.history = {}
47+
M.save()
1748
end
1849

1950
return M

lua/grok/chat/init.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
-- ~/github.com/acris-software/grok-nvim/lua/grok/chat/init.lua
22

33
local M = {}
4+
45
local async = require("plenary.async")
56
local ui = require("grok.ui")
67
local log = require("grok.log")
78
local request = require("grok.chat.request")
9+
local util = require("grok.util")
810

911
function M.chat(prompt)
1012
local config = require("grok").config
@@ -37,6 +39,12 @@ function M.chat(prompt)
3739
end
3840
request.send_request(prompt)
3941
end)
42+
else
43+
-- Directly open the floating input instead of simulating 'i'
44+
vim.schedule(function()
45+
log.debug("Opening floating input with callback: " .. vim.inspect(ui.current_callback))
46+
util.create_floating_input({ callback = ui.current_callback })
47+
end)
4048
end
4149
end)
4250
end

lua/grok/chat/request.lua

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ local function send_request(input)
2727
end)
2828
if not ok then
2929
log.error("Failed to set reasoning line: " .. vim.inspect(err))
30+
vim.notify("UI Error: Failed to update reasoning!", vim.log.levels.ERROR)
3031
end
3132
end)
3233
curl.post(config.base_url .. "/chat/completions", {
@@ -47,6 +48,7 @@ local function send_request(input)
4748
if not ok then
4849
log.error("Failed to set modifiable false after error: " .. vim.inspect(set_err))
4950
end
51+
vim.notify("API Error: Request failed!", vim.log.levels.ERROR)
5052
end)
5153
return
5254
end
@@ -59,13 +61,15 @@ local function send_request(input)
5961
if not ok then
6062
log.error("Failed to set modifiable true for done: " .. vim.inspect(set_err))
6163
end
64+
-- Ensure final response is appended
6265
ui.append_response("\n\n")
6366
ok, set_err = pcall(vim.api.nvim_buf_set_option, ui.current_buf, "modifiable", false)
6467
if not ok then
6568
log.error("Failed to set modifiable false after done: " .. vim.inspect(set_err))
6669
end
70+
history.add("assistant", response)
71+
log.debug("Stream completed, full response: " .. response)
6772
end)
68-
history.add("assistant", response)
6973
return
7074
end
7175
local ok, json = pcall(vim.json.decode, json_str)
@@ -74,6 +78,10 @@ local function send_request(input)
7478
if delta_content ~= "" then
7579
response = response .. delta_content
7680
vim.schedule(function()
81+
if not ui.current_buf or not vim.api.nvim_buf_is_valid(ui.current_buf) then
82+
log.error("Chat buffer invalid during stream")
83+
return
84+
end
7785
if is_first_chunk then
7886
is_first_chunk = false
7987
local set_ok, set_err = pcall(vim.api.nvim_buf_set_option, ui.current_buf, "modifiable", true)
@@ -106,6 +114,8 @@ local function send_request(input)
106114
end
107115
end)
108116
end
117+
else
118+
log.debug("Invalid JSON or no delta in stream chunk: " .. json_str)
109119
end
110120
end
111121
end,
@@ -122,6 +132,24 @@ local function send_request(input)
122132
if not ok then
123133
log.error("Failed to set modifiable false after non-200: " .. vim.inspect(set_err))
124134
end
135+
vim.notify("API Error: Status " .. res.status, vim.log.levels.ERROR)
136+
else
137+
-- Ensure final response is complete
138+
if response ~= "" then
139+
vim.schedule(function()
140+
local ok, set_err = pcall(vim.api.nvim_buf_set_option, ui.current_buf, "modifiable", true)
141+
if not ok then
142+
log.error("Failed to set modifiable true for final response: " .. vim.inspect(set_err))
143+
end
144+
ui.append_response("\n\n")
145+
ok, set_err = pcall(vim.api.nvim_buf_set_option, ui.current_buf, "modifiable", false)
146+
if not ok then
147+
log.error("Failed to set modifiable false after final response: " .. vim.inspect(set_err))
148+
end
149+
history.add("assistant", response)
150+
log.debug("Final response appended: " .. response)
151+
end)
152+
end
125153
end
126154
end)
127155
end,

lua/grok/commands.lua

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,32 @@ local M = {}
44
function M.setup_commands()
55
local log = require("grok.log")
66
vim.api.nvim_create_user_command("Grok", function(opts)
7-
require("grok.chat").chat(opts.args)
7+
require("grok.ui").open_chat_window(function(input)
8+
require("grok.chat").chat(input)
9+
end)
10+
if opts.args and opts.args ~= "" then
11+
require("grok.chat").chat(opts.args)
12+
end
813
log.debug("Grok command executed with args: " .. vim.inspect(opts.args))
914
end, { nargs = "*", desc = "Chat with Grok" })
1015
vim.api.nvim_create_user_command("GrokVisual", function()
1116
local selected_text = require("grok.util").get_visual_selection()
17+
require("grok.ui").open_chat_window(function(input)
18+
require("grok.chat").chat(input)
19+
end)
1220
require("grok.chat").chat(selected_text)
1321
log.debug("GrokVisual command executed with selection: " .. selected_text)
1422
end, { range = true, desc = "Chat with Grok using visual selection" })
1523
vim.api.nvim_create_user_command("GrokClear", function()
16-
require("grok.ui").close_chat_window()
1724
require("grok.chat").clear_history()
25+
local ui = require("grok.ui")
26+
if ui.current_buf and vim.api.nvim_buf_is_valid(ui.current_buf) then
27+
require("grok.ui.render").render_tab_content(ui.current_buf, function(input)
28+
require("grok.chat").chat(input)
29+
end)
30+
end
1831
log.info("GrokClear command executed")
19-
end, { desc = "Clear and close Grok chat window" })
32+
end, { desc = "Clear Grok chat history" })
2033
vim.api.nvim_create_user_command("GrokLog", function()
2134
local log_file = vim.fn.stdpath("data") .. "/grok.log"
2235
vim.cmd("edit " .. log_file)
@@ -25,18 +38,19 @@ function M.setup_commands()
2538
vim.api.nvim_create_user_command("GrokKeymaps", function()
2639
local ui = require("grok.ui")
2740
if ui.current_win and vim.api.nvim_win_is_valid(ui.current_win) then
28-
ui.current_tab = 2
41+
ui.set_current_tab(2)
2942
require("grok.ui.render").render_tab_content(ui.current_buf, function() end)
3043
log.debug("GrokKeymaps switched to tab 2 in UI")
3144
else
32-
local keymaps = {
33-
"In Grok Chat Window:",
34-
" <CR> or i: Open input prompt",
35-
" <Esc>: Close window",
36-
}
37-
vim.notify(table.concat(keymaps, "\n"), vim.log.levels.INFO)
38-
log.debug("GrokKeymaps notified keymaps")
45+
ui.open_chat_window(function() end)
46+
ui.set_current_tab(2)
47+
require("grok.ui.render").render_tab_content(ui.current_buf, function() end)
48+
log.debug("GrokKeymaps opened UI and switched to tab 2")
3949
end
40-
end, { desc = "List Grok-nvim keymaps" })
50+
end, { desc = "Show Grok-nvim keymaps" })
51+
vim.api.nvim_create_user_command("GrokUI", function()
52+
require("grok.ui").toggle_ui()
53+
log.debug("GrokUI command executed")
54+
end, { desc = "Toggle Grok UI" })
4155
end
4256
return M

lua/grok/init.lua

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
local M = {}
44
local commands = require("grok.commands")
55
local log = require("grok.log")
6+
67
function M.setup(opts)
78
local curl = require("plenary.curl")
89
local async = require("plenary.async")
@@ -36,13 +37,37 @@ function M.setup(opts)
3637
temperature = 0.7,
3738
max_tokens = 256,
3839
debug = false,
40+
prompt_position = "center", -- Options: "left", "center", "right"
3941
}, opts or {})
4042
if not M.config.api_key then
4143
vim.notify("GROK_KEY not set in ~/.secrets, environment, or opts!", vim.log.levels.ERROR)
4244
log.error("API key not set in setup")
4345
end
46+
require("grok.util").validate_config(M.config)
4447
M.chat = chat.chat
4548
commands.setup_commands()
46-
log.info("Plugin setup completed")
49+
log.info("Plugin setup completed - grok-nvim v0.1.1")
50+
51+
-- Clean up Grok UI and buffers on Neovim exit
52+
vim.api.nvim_create_autocmd("VimLeavePre", {
53+
callback = function()
54+
local ui = require("grok.ui")
55+
if ui.current_win and vim.api.nvim_win_is_valid(ui.current_win) then
56+
require("grok.ui").close_chat_window()
57+
end
58+
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
59+
if vim.api.nvim_buf_is_valid(buf) then
60+
local buftype = vim.api.nvim_buf_get_option(buf, "buftype")
61+
local filetype = vim.api.nvim_buf_get_option(buf, "filetype")
62+
if buftype == "prompt" or filetype == "markdown" then
63+
pcall(vim.api.nvim_buf_delete, buf, { force = true })
64+
end
65+
end
66+
end
67+
log.debug("Cleaned up Grok UI and buffers on VimLeavePre")
68+
end,
69+
desc = "Clean up Grok UI and buffers before exiting Neovim",
70+
})
4771
end
72+
4873
return M

lua/grok/log/core.lua

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ local log_file = vim.fn.stdpath("data") .. "/grok.log"
44
local max_log_size = 1024 * 1024 -- 1MB
55
local last_message = nil
66
local repeat_count = 0
7+
local message_cache = {} -- Cache for throttling: {message = timestamp}
8+
local throttle_interval = 5000
79

810
local function rotate_log()
911
local file_info = vim.uv.fs_stat(log_file)
@@ -24,21 +26,41 @@ local function write_log(full_message)
2426
end
2527

2628
local function log(message, level)
27-
if require("grok").config.debug then
28-
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
29-
local prefix = level or ""
30-
local full_message = timestamp .. " " .. prefix .. message
31-
if full_message == last_message then
32-
repeat_count = repeat_count + 1
33-
return -- Throttle
34-
else
35-
if repeat_count > 0 then
36-
local repeat_note = timestamp .. " [REPEAT] Previous message repeated " .. repeat_count .. " times"
37-
write_log(repeat_note)
38-
end
39-
repeat_count = 0
40-
last_message = full_message
41-
write_log(full_message)
29+
if not require("grok").config.debug then
30+
return
31+
end
32+
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
33+
local prefix = level or ""
34+
local full_message = timestamp .. " " .. prefix .. message
35+
local now = vim.loop.now()
36+
37+
-- Check if message was logged recently
38+
local last_logged = message_cache[message]
39+
if last_logged and (now - last_logged) < throttle_interval then
40+
return -- Throttle: skip if logged within throttle_interval
41+
end
42+
43+
-- Update cache with current timestamp
44+
message_cache[message] = now
45+
46+
-- Handle repeated messages
47+
if full_message == last_message then
48+
repeat_count = repeat_count + 1
49+
return -- Throttle consecutive identical messages
50+
else
51+
if repeat_count > 0 then
52+
local repeat_note = timestamp .. " [REPEAT] Previous message repeated " .. repeat_count .. " times"
53+
write_log(repeat_note)
54+
end
55+
repeat_count = 0
56+
last_message = full_message
57+
write_log(full_message)
58+
end
59+
60+
-- Clean up old cache entries
61+
for msg, ts in pairs(message_cache) do
62+
if (now - ts) >= throttle_interval then
63+
message_cache[msg] = nil
4264
end
4365
end
4466
end

0 commit comments

Comments
 (0)