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
2 changes: 1 addition & 1 deletion lua/opencode/commands/handlers/agent.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ M.actions.switch_mode = Promise.async(function()
local modes = config_file.get_opencode_agents():await() --[[@as string[] ]]
local current_index = util.index_of(modes, state.store.get('current_mode'))

if current_index == -1 then
if current_index == nil then
current_index = 0
end

Expand Down
13 changes: 12 additions & 1 deletion lua/opencode/config_file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,27 @@ M.get_workspace_snapshot_path = Promise.async(function()
return home .. '/.local/share/opencode/snapshot/' .. project.id
end)

local _providers_render_callback = false

---@return Promise<OpencodeProvidersResponse|nil>
function M.get_opencode_providers()
if not M.providers_promise then
local state = require('opencode.state')
M.providers_promise = state.api_client:list_providers()
end
return M.providers_promise:catch(function(err)
local wrapped = M.providers_promise:catch(function(err)
vim.notify('Error fetching Opencode providers: ' .. vim.inspect(err), vim.log.levels.ERROR)
return nil
end)
if not _providers_render_callback then
_providers_render_callback = true
wrapped:finally(function()
local ok, _ = pcall(function()
require('opencode.ui.topbar').render()
end)
end)
end
return wrapped
end

--- Get model information for a specific provider and model
Expand Down
7 changes: 6 additions & 1 deletion lua/opencode/state/renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ function M.update_pending_permissions(mutator)
end
---@param cost number
function M.set_cost(cost)
if not cost or cost <= 0 then
return
end
return store.set('cost', cost)
end

Expand All @@ -42,7 +45,9 @@ end
function M.set_stats(tokens_count, cost)
return store.batch(function()
store.set('tokens_count', tokens_count)
store.set('cost', cost)
if cost and cost > 0 then
store.set('cost', cost)
end
end)
end

Expand Down
9 changes: 8 additions & 1 deletion lua/opencode/ui/renderer/events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,15 @@ function M.on_part_updated(properties, revert_index)
end
end

-- step-start / step-finish are bookkeeping only — nothing to render
if part.type == 'step-start' or part.type == 'step-finish' then
if part.type == 'step-finish' and part.tokens then
local tokens = part.tokens
if tokens.input > 0 and part.cost and type(part.cost) == 'number' then
state.renderer.set_stats(tokens.input + tokens.output + tokens.cache.read + tokens.cache.write, part.cost)
elseif tokens.input > 0 then
state.renderer.set_tokens_count(tokens.input + tokens.output + tokens.cache.read + tokens.cache.write)
end
end
return
end

Expand Down
34 changes: 15 additions & 19 deletions lua/opencode/ui/topbar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,22 @@ local function format_token_info()
model_info = nil
end
local limit = state.tokens_count and model_info and model_info.limit and model_info.limit.context or 0
table.insert(parts, util.format_number(state.tokens_count) or nil)
local formatted_count = util.format_number(state.tokens_count)
if formatted_count then
table.insert(parts, formatted_count)
end
if limit > 0 then
table.insert(parts, util.format_percentage(state.tokens_count / limit) or nil)
local formatted_pct = util.format_percentage(state.tokens_count / limit)
if formatted_pct then
table.insert(parts, formatted_pct)
end
end
end
if config.ui.display_cost and state.cost then
table.insert(parts, util.format_cost(state.cost) or nil)
if config.ui.display_cost and state.cost and state.cost > 0 then
local formatted_cost = util.format_cost(state.cost)
if formatted_cost then
table.insert(parts, formatted_cost)
end
end
end

Expand All @@ -37,21 +46,8 @@ local function format_token_info()
return result
end

local function create_winbar_text(description, token_info, win_width)
local left_content = ''
local right_content = token_info

local desc_width = win_width - util.strdisplaywidth(left_content) - util.strdisplaywidth(right_content)

local desc_formatted
if #description >= desc_width then
local ellipsis = '... '
desc_formatted = description:sub(1, desc_width - #ellipsis) .. ellipsis
else
desc_formatted = description .. string.rep(' ', math.floor(desc_width - #description))
end

return left_content .. desc_formatted .. right_content
local function create_winbar_text(description, token_info, _)
return description .. '%=' .. token_info
end

local function get_session_desc()
Expand Down
Loading