fixing configuration to change the windows
This commit is contained in:
@@ -147,6 +147,24 @@ function M.error(message, data)
|
||||
M.log("error", "ERROR: " .. message, data)
|
||||
end
|
||||
|
||||
--- Log warning
|
||||
---@param message string
|
||||
---@param data? table
|
||||
function M.warning(message, data)
|
||||
M.log("warning", "WARN: " .. message, data)
|
||||
end
|
||||
|
||||
--- Add log entry (compatibility function for scheduler)
|
||||
--- Accepts {type = "info", message = "..."} format
|
||||
---@param entry table Log entry with type and message
|
||||
function M.add(entry)
|
||||
if entry.type == "clear" then
|
||||
M.clear()
|
||||
return
|
||||
end
|
||||
M.log(entry.type or "info", entry.message or "", entry.data)
|
||||
end
|
||||
|
||||
--- Log thinking/reasoning step
|
||||
---@param step string Description of what's happening
|
||||
function M.thinking(step)
|
||||
|
||||
@@ -24,6 +24,8 @@ local state = {
|
||||
referenced_files = {},
|
||||
target_width = nil, -- Store the target width to maintain it
|
||||
agent_mode = false, -- Whether agent mode is enabled (can make file changes)
|
||||
log_listener_id = nil, -- Listener ID for LLM logs
|
||||
show_logs = true, -- Whether to show LLM logs in chat
|
||||
}
|
||||
|
||||
--- Get the ask window configuration
|
||||
@@ -59,6 +61,7 @@ local function create_output_buffer()
|
||||
"║ C-Enter → send ║",
|
||||
"║ C-n → new chat ║",
|
||||
"║ C-f → add current file ║",
|
||||
"║ L → toggle LLM logs ║",
|
||||
"║ :CoderType → switch mode ║",
|
||||
"║ q → close │ K/J → jump ║",
|
||||
"╚═════════════════════════════════╝",
|
||||
@@ -195,6 +198,11 @@ local function setup_output_keymaps(buf)
|
||||
M.copy_last_response()
|
||||
end, opts)
|
||||
|
||||
-- Toggle LLM logs with L
|
||||
vim.keymap.set("n", "L", function()
|
||||
M.toggle_logs()
|
||||
end, opts)
|
||||
|
||||
-- Jump to input with i or J
|
||||
vim.keymap.set("n", "i", function()
|
||||
M.focus_input()
|
||||
@@ -276,6 +284,88 @@ local function setup_width_autocmd()
|
||||
})
|
||||
end
|
||||
|
||||
--- Append log entry to output buffer
|
||||
---@param entry table Log entry from agent/logs
|
||||
local function append_log_to_output(entry)
|
||||
if not state.show_logs then
|
||||
return
|
||||
end
|
||||
|
||||
if not state.output_buf or not vim.api.nvim_buf_is_valid(state.output_buf) then
|
||||
return
|
||||
end
|
||||
|
||||
-- Skip clear events
|
||||
if entry.level == "clear" then
|
||||
return
|
||||
end
|
||||
|
||||
-- Format the log entry with icons
|
||||
local icons = {
|
||||
info = "ℹ️",
|
||||
debug = "🔍",
|
||||
request = "📤",
|
||||
response = "📥",
|
||||
tool = "🔧",
|
||||
error = "❌",
|
||||
warning = "⚠️",
|
||||
}
|
||||
|
||||
local icon = icons[entry.level] or "•"
|
||||
local formatted = string.format("[%s] %s %s", entry.timestamp, icon, entry.message)
|
||||
|
||||
vim.schedule(function()
|
||||
if not state.output_buf or not vim.api.nvim_buf_is_valid(state.output_buf) then
|
||||
return
|
||||
end
|
||||
|
||||
vim.bo[state.output_buf].modifiable = true
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(state.output_buf, 0, -1, false)
|
||||
|
||||
-- Add a subtle log line
|
||||
table.insert(lines, " " .. formatted)
|
||||
|
||||
vim.api.nvim_buf_set_lines(state.output_buf, 0, -1, false, lines)
|
||||
vim.bo[state.output_buf].modifiable = false
|
||||
|
||||
-- Scroll to bottom
|
||||
if state.output_win and vim.api.nvim_win_is_valid(state.output_win) then
|
||||
local line_count = vim.api.nvim_buf_line_count(state.output_buf)
|
||||
pcall(vim.api.nvim_win_set_cursor, state.output_win, { line_count, 0 })
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Setup log listener for LLM logs
|
||||
local function setup_log_listener()
|
||||
-- Remove existing listener if any
|
||||
if state.log_listener_id then
|
||||
pcall(function()
|
||||
local logs = require("codetyper.agent.logs")
|
||||
logs.remove_listener(state.log_listener_id)
|
||||
end)
|
||||
state.log_listener_id = nil
|
||||
end
|
||||
|
||||
-- Add new listener
|
||||
local ok, logs = pcall(require, "codetyper.agent.logs")
|
||||
if ok then
|
||||
state.log_listener_id = logs.add_listener(append_log_to_output)
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove log listener
|
||||
local function remove_log_listener()
|
||||
if state.log_listener_id then
|
||||
pcall(function()
|
||||
local logs = require("codetyper.agent.logs")
|
||||
logs.remove_listener(state.log_listener_id)
|
||||
end)
|
||||
state.log_listener_id = nil
|
||||
end
|
||||
end
|
||||
|
||||
--- Open the ask panel
|
||||
function M.open()
|
||||
-- Use the is_open() function which validates window state
|
||||
@@ -335,6 +425,9 @@ function M.open()
|
||||
|
||||
state.is_open = true
|
||||
|
||||
-- Setup log listener for LLM logs
|
||||
setup_log_listener()
|
||||
|
||||
-- Setup autocmd to maintain width
|
||||
setup_width_autocmd()
|
||||
|
||||
@@ -366,6 +459,9 @@ function M.open()
|
||||
state.is_open = false
|
||||
state.target_width = nil
|
||||
|
||||
-- Remove log listener
|
||||
remove_log_listener()
|
||||
|
||||
-- Clean up autocmd groups
|
||||
pcall(vim.api.nvim_del_augroup_by_id, close_group)
|
||||
if ask_augroup then
|
||||
@@ -466,6 +562,9 @@ end
|
||||
|
||||
--- Close the ask panel
|
||||
function M.close()
|
||||
-- Remove the log listener
|
||||
remove_log_listener()
|
||||
|
||||
-- Remove the width maintenance autocmd first
|
||||
if ask_augroup then
|
||||
pcall(vim.api.nvim_del_augroup_by_id, ask_augroup)
|
||||
@@ -796,6 +895,7 @@ function M.clear_history()
|
||||
"║ C-Enter → send ║",
|
||||
"║ C-n → new chat ║",
|
||||
"║ C-f → add current file ║",
|
||||
"║ L → toggle LLM logs ║",
|
||||
"║ :CoderType → switch mode ║",
|
||||
"║ q → close │ K/J → jump ║",
|
||||
"╚═════════════════════════════════╝",
|
||||
@@ -881,4 +981,18 @@ function M.get_history()
|
||||
return state.history
|
||||
end
|
||||
|
||||
--- Toggle LLM log visibility in chat
|
||||
---@return boolean New state
|
||||
function M.toggle_logs()
|
||||
state.show_logs = not state.show_logs
|
||||
utils.notify("LLM logs " .. (state.show_logs and "enabled" or "disabled"))
|
||||
return state.show_logs
|
||||
end
|
||||
|
||||
--- Check if logs are enabled
|
||||
---@return boolean
|
||||
function M.logs_enabled()
|
||||
return state.show_logs
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -361,292 +361,4 @@ function M.format_messages_for_claude(messages)
|
||||
return formatted
|
||||
end
|
||||
|
||||
--- Generate with tool use support for agentic mode
|
||||
---@param messages table[] Conversation history
|
||||
---@param context table Context information
|
||||
---@param tool_definitions table Tool definitions
|
||||
---@param callback fun(response: table|nil, error: string|nil) Callback with raw response
|
||||
function M.generate_with_tools(messages, context, tool_definitions, callback)
|
||||
local api_key = get_api_key()
|
||||
if not api_key then
|
||||
callback(nil, "Claude API key not configured")
|
||||
return
|
||||
end
|
||||
|
||||
local tools_module = require("codetyper.agent.tools")
|
||||
local agent_prompts = require("codetyper.prompts.agent")
|
||||
|
||||
-- Build system prompt with agent instructions
|
||||
local system_prompt = llm.build_system_prompt(context)
|
||||
system_prompt = system_prompt .. "\n\n" .. agent_prompts.system
|
||||
system_prompt = system_prompt .. "\n\n" .. agent_prompts.tool_instructions
|
||||
|
||||
-- Build request body with tools
|
||||
local body = {
|
||||
model = get_model(),
|
||||
max_tokens = 4096,
|
||||
system = system_prompt,
|
||||
messages = M.format_messages_for_claude(messages),
|
||||
tools = tools_module.to_claude_format(),
|
||||
}
|
||||
|
||||
local json_body = vim.json.encode(body)
|
||||
|
||||
local cmd = {
|
||||
"curl",
|
||||
"-s",
|
||||
"-X", "POST",
|
||||
API_URL,
|
||||
"-H", "Content-Type: application/json",
|
||||
"-H", "x-api-key: " .. api_key,
|
||||
"-H", "anthropic-version: 2023-06-01",
|
||||
"-d", json_body,
|
||||
}
|
||||
|
||||
vim.fn.jobstart(cmd, {
|
||||
stdout_buffered = true,
|
||||
on_stdout = function(_, data)
|
||||
if not data or #data == 0 or (data[1] == "" and #data == 1) then
|
||||
return
|
||||
end
|
||||
|
||||
local response_text = table.concat(data, "\n")
|
||||
local ok, response = pcall(vim.json.decode, response_text)
|
||||
|
||||
if not ok then
|
||||
vim.schedule(function()
|
||||
callback(nil, "Failed to parse Claude response")
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
if response.error then
|
||||
vim.schedule(function()
|
||||
callback(nil, response.error.message or "Claude API error")
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- Return raw response for parser to handle
|
||||
vim.schedule(function()
|
||||
callback(response, nil)
|
||||
end)
|
||||
end,
|
||||
on_stderr = function(_, data)
|
||||
if data and #data > 0 and data[1] ~= "" then
|
||||
vim.schedule(function()
|
||||
callback(nil, "Claude API request failed: " .. table.concat(data, "\n"))
|
||||
end)
|
||||
end
|
||||
end,
|
||||
on_exit = function(_, code)
|
||||
if code ~= 0 then
|
||||
vim.schedule(function()
|
||||
callback(nil, "Claude API request failed with code: " .. code)
|
||||
end)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
--- Format messages for Claude API
|
||||
---@param messages table[] Internal message format
|
||||
---@return table[] Claude API message format
|
||||
function M.format_messages_for_claude(messages)
|
||||
local formatted = {}
|
||||
|
||||
for _, msg in ipairs(messages) do
|
||||
if msg.role == "user" then
|
||||
if type(msg.content) == "table" then
|
||||
-- Tool results
|
||||
table.insert(formatted, {
|
||||
role = "user",
|
||||
content = msg.content,
|
||||
})
|
||||
else
|
||||
table.insert(formatted, {
|
||||
role = "user",
|
||||
content = msg.content,
|
||||
})
|
||||
end
|
||||
elseif msg.role == "assistant" then
|
||||
-- Build content array for assistant messages
|
||||
local content = {}
|
||||
|
||||
-- Add text if present
|
||||
if msg.content and msg.content ~= "" then
|
||||
table.insert(content, {
|
||||
type = "text",
|
||||
text = msg.content,
|
||||
})
|
||||
end
|
||||
|
||||
-- Add tool uses if present
|
||||
if msg.tool_calls then
|
||||
for _, tool_call in ipairs(msg.tool_calls) do
|
||||
table.insert(content, {
|
||||
type = "tool_use",
|
||||
id = tool_call.id,
|
||||
name = tool_call.name,
|
||||
input = tool_call.parameters,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if #content > 0 then
|
||||
table.insert(formatted, {
|
||||
role = "assistant",
|
||||
content = content,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return formatted
|
||||
end
|
||||
|
||||
--- Generate with tool use support for agentic mode
|
||||
---@param messages table[] Conversation history
|
||||
---@param context table Context information
|
||||
---@param tool_definitions table Tool definitions
|
||||
---@param callback fun(response: table|nil, error: string|nil) Callback with raw response
|
||||
function M.generate_with_tools(messages, context, tool_definitions, callback)
|
||||
local api_key = get_api_key()
|
||||
if not api_key then
|
||||
callback(nil, "Claude API key not configured")
|
||||
return
|
||||
end
|
||||
|
||||
local tools_module = require("codetyper.agent.tools")
|
||||
local agent_prompts = require("codetyper.prompts.agent")
|
||||
|
||||
-- Build system prompt with agent instructions
|
||||
local system_prompt = llm.build_system_prompt(context)
|
||||
system_prompt = system_prompt .. "\n\n" .. agent_prompts.system
|
||||
system_prompt = system_prompt .. "\n\n" .. agent_prompts.tool_instructions
|
||||
|
||||
-- Build request body with tools
|
||||
local body = {
|
||||
model = get_model(),
|
||||
max_tokens = 4096,
|
||||
system = system_prompt,
|
||||
messages = M.format_messages_for_claude(messages),
|
||||
tools = tools_module.to_claude_format(),
|
||||
}
|
||||
|
||||
local json_body = vim.json.encode(body)
|
||||
|
||||
local cmd = {
|
||||
"curl",
|
||||
"-s",
|
||||
"-X", "POST",
|
||||
API_URL,
|
||||
"-H", "Content-Type: application/json",
|
||||
"-H", "x-api-key: " .. api_key,
|
||||
"-H", "anthropic-version: 2023-06-01",
|
||||
"-d", json_body,
|
||||
}
|
||||
|
||||
vim.fn.jobstart(cmd, {
|
||||
stdout_buffered = true,
|
||||
on_stdout = function(_, data)
|
||||
if not data or #data == 0 or (data[1] == "" and #data == 1) then
|
||||
return
|
||||
end
|
||||
|
||||
local response_text = table.concat(data, "\n")
|
||||
local ok, response = pcall(vim.json.decode, response_text)
|
||||
|
||||
if not ok then
|
||||
vim.schedule(function()
|
||||
callback(nil, "Failed to parse Claude response")
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
if response.error then
|
||||
vim.schedule(function()
|
||||
callback(nil, response.error.message or "Claude API error")
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- Return raw response for parser to handle
|
||||
vim.schedule(function()
|
||||
callback(response, nil)
|
||||
end)
|
||||
end,
|
||||
on_stderr = function(_, data)
|
||||
if data and #data > 0 and data[1] ~= "" then
|
||||
vim.schedule(function()
|
||||
callback(nil, "Claude API request failed: " .. table.concat(data, "\n"))
|
||||
end)
|
||||
end
|
||||
end,
|
||||
on_exit = function(_, code)
|
||||
if code ~= 0 then
|
||||
vim.schedule(function()
|
||||
callback(nil, "Claude API request failed with code: " .. code)
|
||||
end)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
--- Format messages for Claude API
|
||||
---@param messages table[] Internal message format
|
||||
---@return table[] Claude API message format
|
||||
function M.format_messages_for_claude(messages)
|
||||
local formatted = {}
|
||||
|
||||
for _, msg in ipairs(messages) do
|
||||
if msg.role == "user" then
|
||||
if type(msg.content) == "table" then
|
||||
-- Tool results
|
||||
table.insert(formatted, {
|
||||
role = "user",
|
||||
content = msg.content,
|
||||
})
|
||||
else
|
||||
table.insert(formatted, {
|
||||
role = "user",
|
||||
content = msg.content,
|
||||
})
|
||||
end
|
||||
elseif msg.role == "assistant" then
|
||||
-- Build content array for assistant messages
|
||||
local content = {}
|
||||
|
||||
-- Add text if present
|
||||
if msg.content and msg.content ~= "" then
|
||||
table.insert(content, {
|
||||
type = "text",
|
||||
text = msg.content,
|
||||
})
|
||||
end
|
||||
|
||||
-- Add tool uses if present
|
||||
if msg.tool_calls then
|
||||
for _, tool_call in ipairs(msg.tool_calls) do
|
||||
table.insert(content, {
|
||||
type = "tool_use",
|
||||
id = tool_call.id,
|
||||
name = tool_call.name,
|
||||
input = tool_call.parameters,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if #content > 0 then
|
||||
table.insert(formatted, {
|
||||
role = "assistant",
|
||||
content = content,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return formatted
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user