Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lua/opencode/api_client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ function OpencodeApiClient:_ensure_base_url()
end
end

if not state.opencode_server.url then
return false
end

self.base_url = state.opencode_server.url:gsub('/$', '')
return true
end
Expand All @@ -49,7 +53,7 @@ end
--- @return Promise<any> promise
function OpencodeApiClient:_call(endpoint, method, body, query)
if not self:_ensure_base_url() then
return nil
return require('opencode.promise').new():reject('No server base url')
end
local url = self.base_url .. endpoint

Expand Down Expand Up @@ -221,7 +225,7 @@ end

--- Create and send a new message to a session
--- @param id string Session ID (required)
--- @param message_data {messageID?: string, model?: {providerID: string, modelID: string}, agent?: string, system?: string, tools?: table<string, boolean>, parts: Part[]} Message creation data
--- @param message_data {messageID?: string, model?: {providerID: string, modelID: string}, agent?: string, system?: string, tools?: table<string, boolean>, parts: OpencodeMessagePart[]} Message creation data
--- @param directory string|nil Directory path
--- @return Promise<{info: MessageInfo, parts: OpencodeMessagePart[]}>
function OpencodeApiClient:create_message(id, message_data, directory)
Expand Down Expand Up @@ -393,7 +397,7 @@ function OpencodeApiClient:subscribe_to_events(directory, on_event)
chunk = chunk:gsub('^data:%s*', '')
local ok, event = pcall(vim.json.decode, vim.trim(chunk))
if ok and event then
on_event(event)
on_event(event --[[@as table]])
end
end)
end
Expand Down
8 changes: 4 additions & 4 deletions lua/opencode/config_file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ end
function M.get_model_info(provider, model)
local config_file = require('opencode.config_file')
local providers = config_file.get_opencode_providers() or {}
providers = vim.tbl_filter(function(p)
local filtered_providers = vim.tbl_filter(function(p)
return p.id == provider
end, providers)
end, providers.providers)

if #providers == 0 then
if #filtered_providers == 0 then
return nil
end

return providers[1] and providers[1].models and providers[1].models[model] or nil
return filtered_providers[1] and filtered_providers[1].models and filtered_providers[1].models[model] or nil
end

function M.get_opencode_agents()
Expand Down
10 changes: 5 additions & 5 deletions lua/opencode/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ end
---@param context_key string
---@return boolean
function M.is_context_enabled(context_key)
local is_enabled = vim.tbl_get(config, 'context', context_key, 'enabled')
local is_enabled = vim.tbl_get(config --[[@as table]], 'context', context_key, 'enabled')
local is_state_enabled = vim.tbl_get(state, 'current_context_config', context_key, 'enabled')

if is_state_enabled ~= nil then
Expand All @@ -76,7 +76,7 @@ function M.get_diagnostics(buf)
return {}
end

local global_conf = vim.tbl_get(config, 'context', 'diagnostics') or {}
local global_conf = vim.tbl_get(config --[[@as table]], 'context', 'diagnostics') or {}
local diagnostic_conf = vim.tbl_deep_extend('force', global_conf, current_conf) or {}

local severity_levels = {}
Expand Down Expand Up @@ -264,7 +264,8 @@ function M.get_current_cursor_data(buf, win)
end

local cursor_pos = vim.fn.getcurpos(win)
local cursor_content = vim.trim(vim.api.nvim_buf_get_lines(buf, cursor_pos[2] - 1, cursor_pos[2], false)[1] or '')
local start_line = (cursor_pos[2] - 1) --[[@as integer]]
local cursor_content = vim.trim(vim.api.nvim_buf_get_lines(buf, start_line, cursor_pos[2], false)[1] or '')
return { line = cursor_pos[2], column = cursor_pos[3], line_content = cursor_content }
end

Expand Down Expand Up @@ -384,7 +385,6 @@ end
function M.format_message(prompt, opts)
opts = opts or config.context
local context = M.delta_context(opts)
context.prompt = prompt

local parts = { { type = 'text', text = prompt } }

Expand Down Expand Up @@ -430,7 +430,7 @@ end

--- Extracts context from an OpencodeMessage (with parts)
---@param message { parts: OpencodeMessagePart[] }
---@return { prompt: string, selected_text: string|nil, current_file: string|nil, mentioned_files: string[]|nil}
---@return { prompt: string|nil, selected_text: string|nil, current_file: string|nil, mentioned_files: string[]|nil}
function M.extract_from_opencode_message(message)
local ctx = { prompt = nil, selected_text = nil, current_file = nil }

Expand Down
4 changes: 4 additions & 0 deletions lua/opencode/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ end
--- @param prompt string The message prompt to send.
--- @param opts? SendMessageOpts
function M.send_message(prompt, opts)
if not state.active_session or not state.active_session.id then
return false
end

local mentioned_files = context.context.mentioned_files or {}
local allowed, err_msg = util.check_prompt_allowed(config.prompt_guard, mentioned_files)

Expand Down
2 changes: 2 additions & 0 deletions lua/opencode/health.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ local function check_configuration()
return
end

---@cast config OpencodeConfig

local valid_positions = { 'left', 'right', 'top', 'bottom' }
if not vim.tbl_contains(valid_positions, config.ui.position) then
health.warn(
Expand Down
2 changes: 1 addition & 1 deletion lua/opencode/keymap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ end

-- Setup window-specific keymaps (shared helper for input/output windows)
---@param keymap_config table Window keymap configuration
---@param buf_id number Buffer ID to set keymaps for
---@param buf_id integer Buffer ID to set keymaps for
function M.setup_window_keymaps(keymap_config, buf_id)
if not vim.api.nvim_buf_is_valid(buf_id) then
return
Expand Down
6 changes: 3 additions & 3 deletions lua/opencode/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
---@field input_content table
---@field is_opencode_focused boolean
---@field last_focused_opencode_window string|nil
---@field last_input_window_position number|nil
---@field last_output_window_position number|nil
---@field last_code_win_before_opencode number|nil
---@field last_input_window_position integer[]|nil
---@field last_output_window_position integer[]|nil
---@field last_code_win_before_opencode integer|nil
---@field current_code_buf number|nil
---@field display_route any|nil
---@field current_mode string
Expand Down
2 changes: 1 addition & 1 deletion lua/opencode/throttling_emitter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ local M = {}
--- @field queue table[] Queue of pending items to be processed
--- @field drain_scheduled boolean Whether a drain is already scheduled
--- @field process_fn fun(table): nil Function to process the queue of events
--- @field drain_interval_ms number Interval between drains in milliseconds
--- @field drain_interval_ms integer Interval between drains in milliseconds
--- @field enqueue fun(self: ThrottlingEmitter, item: any) Enqueue an item for batch processing
--- @field clear fun(self: ThrottlingEmitter) Clear the queue and cancel any pending drain
local ThrottlingEmitter = {}
Expand Down
2 changes: 1 addition & 1 deletion lua/opencode/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@

---@class OpencodeDebugConfig
---@field enabled boolean
---@field capture_streamed_events any[]
---@field capture_streamed_events boolean

--- @class OpencodeProviders
--- @field [string] string[]
Expand Down
2 changes: 1 addition & 1 deletion lua/opencode/ui/autocmds.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function M.setup_resize_handler(windows)
vim.api.nvim_create_autocmd('WinResized', {
group = resize_group,
callback = function(args)
local win = tonumber(args.match)
local win = tonumber(args.match) --[[@as integer]]
if not win or not vim.api.nvim_win_is_valid(win) or not output_window.mounted() then
return
end
Expand Down
50 changes: 27 additions & 23 deletions lua/opencode/ui/footer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ local loading_animation = require('opencode.ui.loading_animation')
local M = {}

function M.render()
local windows = state.windows
if not output_window.mounted(windows) or not M.mounted(windows) then
if not output_window.mounted() or not M.mounted() then
return
end
---@cast state.windows { output_win: integer }

local segments = {}

Expand Down Expand Up @@ -46,23 +46,22 @@ function M.render()
append_to_footer(restore_point_text)
end

---@diagnostic disable-next-line: need-check-nil
local win_width = vim.api.nvim_win_get_width(windows.output_win)
local win_width = vim.api.nvim_win_get_width(state.windows.output_win)
local footer_text = table.concat(segments, ' | ') .. ' '
footer_text = string.rep(' ', win_width - #footer_text) .. footer_text

M.set_content({ footer_text })
end

---@param windows OpencodeWindowState
function M._build_footer_win_config(windows)
---@param output_win integer
function M._build_footer_win_config(output_win)
return {
relative = 'win',
win = windows.output_win,
win = output_win,
anchor = 'SW',
width = vim.api.nvim_win_get_width(windows.output_win),
width = vim.api.nvim_win_get_width(output_win),
height = 1,
row = vim.api.nvim_win_get_height(windows.output_win) - 1,
row = vim.api.nvim_win_get_height(output_win) - 1,
col = 0,
focusable = false,
style = 'minimal',
Expand All @@ -82,7 +81,11 @@ local function on_job_count_changed(_, new, old)
end

function M.setup(windows)
windows.footer_win = vim.api.nvim_open_win(windows.footer_buf, false, M._build_footer_win_config(windows))
if not windows.output_win then
return false
end

windows.footer_win = vim.api.nvim_open_win(windows.footer_buf, false, M._build_footer_win_config(windows.output_win))
vim.api.nvim_set_option_value('winhl', 'Normal:OpenCodeHint', { win = windows.footer_win })

-- for stats changes
Expand All @@ -95,7 +98,9 @@ function M.setup(windows)
end

function M.close()
if state.windows then
if M.mounted() then
---@cast state.windows { footer_win: integer, footer_buf: integer }

pcall(vim.api.nvim_win_close, state.windows.footer_win, true)
pcall(vim.api.nvim_buf_delete, state.windows.footer_buf, { force = true })
end
Expand All @@ -112,15 +117,17 @@ function M.mounted(windows)
return windows
and windows.footer_win
and vim.api.nvim_win_is_valid(windows.footer_win)
and windows.output_win
and vim.api.nvim_win_is_valid(windows.output_win)
and windows.footer_buf
end

function M.update_window(windows)
if not M.mounted(windows) then
return
end

vim.api.nvim_win_set_config(windows.footer_win, M._build_footer_win_config(windows))
vim.api.nvim_win_set_config(windows.footer_win, M._build_footer_win_config(windows.output_win))
M.render()
end

Expand All @@ -132,29 +139,26 @@ function M.create_buf()
end

function M.clear()
local windows = state.windows
if not M.mounted() or not windows then
if not M.mounted() then
return
end
---@cast state.windows { footer_buf: integer }

local foot_ns_id = vim.api.nvim_create_namespace('opencode_footer')
vim.api.nvim_buf_clear_namespace(windows.footer_buf, foot_ns_id, 0, -1)
vim.api.nvim_buf_clear_namespace(state.windows.footer_buf, foot_ns_id, 0, -1)

M.set_content({})
--
-- state.tokens_count = 0
-- state.cost = 0
end

function M.set_content(lines)
local windows = state.windows
if not M.mounted() or not windows then
if not M.mounted() then
return
end
---@cast state.windows { footer_buf: integer }

vim.api.nvim_set_option_value('modifiable', true, { buf = windows.footer_buf })
vim.api.nvim_buf_set_lines(windows.footer_buf, 0, -1, false, lines)
vim.api.nvim_set_option_value('modifiable', false, { buf = windows.footer_buf })
vim.api.nvim_set_option_value('modifiable', true, { buf = state.windows.footer_buf })
vim.api.nvim_buf_set_lines(state.windows.footer_buf, 0, -1, false, lines)
vim.api.nvim_set_option_value('modifiable', false, { buf = state.windows.footer_buf })
end

return M
12 changes: 8 additions & 4 deletions lua/opencode/ui/mention.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
local config = require('opencode.config')

local M = {}

local mentions_namespace = vim.api.nvim_create_namespace('OpencodeMentions')
Expand All @@ -25,6 +23,7 @@ function M.highlight_all_mentions(buf, callback)
if not mention_start then
break
end
---@cast mention_start integer

if callback then
callback(line:sub(mention_start + 1, mention_end), row, mention_start, mention_end)
Expand Down Expand Up @@ -82,7 +81,7 @@ function M.highlight_mentions_in_output(output, text, mentions, start_line)
end_col = col_end,
hl_group = 'OpencodeMention',
priority = 1000,
})
} --[[@as OutputExtmark]])
break
end

Expand All @@ -91,9 +90,14 @@ function M.highlight_mentions_in_output(output, text, mentions, start_line)
end
end
end

local function insert_mention(windows, row, col, name)
local current_line = vim.api.nvim_buf_get_lines(windows.input_buf, row - 1, row, false)[1]

if not current_line then
return
end

local insert_name = '@' .. name .. ' '

local new_line = current_line:sub(1, col) .. insert_name .. current_line:sub(col + 2)
Expand All @@ -111,7 +115,7 @@ function M.mention(get_name)

get_name(function(name)
vim.schedule(function()
if not windows or not name then
if not windows or not windows.input_win or not name then
return
end
local cursor_pos = vim.api.nvim_win_get_cursor(windows.input_win)
Expand Down
Loading