From e60f56d91e86d3a670fb7730decd211ad834f2fb Mon Sep 17 00:00:00 2001 From: Cameron Ring Date: Tue, 4 Nov 2025 14:49:49 -0800 Subject: [PATCH] refactor: carefully set model from session When loading a session, clear state.current_model and set it to the model used by the most recent message. Topbar shouldn't set a model as a side effect, it should just display what's been selected. Add `core.initialize_current_model()` which will initialize state.current_model to the default from the config_file if it hasn't been set --- lua/opencode/api.lua | 2 +- lua/opencode/core.lua | 23 ++++++++++++++++- lua/opencode/state.lua | 2 -- lua/opencode/ui/renderer.lua | 50 ++++++++++++++++++++++++------------ lua/opencode/ui/topbar.lua | 11 +++----- 5 files changed, 60 insertions(+), 28 deletions(-) diff --git a/lua/opencode/api.lua b/lua/opencode/api.lua index b22cb587..59c8729a 100644 --- a/lua/opencode/api.lua +++ b/lua/opencode/api.lua @@ -355,7 +355,7 @@ function M.initialize() vim.notify('Failed to create new session', vim.log.levels.ERROR) return end - if not state.current_model then + if not core.initialize_current_model() or not state.current_model then vim.notify('No model selected', vim.log.levels.ERROR) return end diff --git a/lua/opencode/core.lua b/lua/opencode/core.lua index 9ffb2389..026b134a 100644 --- a/lua/opencode/core.lua +++ b/lua/opencode/core.lua @@ -25,6 +25,9 @@ function M.select_session(parent_id) end return end + -- clear the model so it can be set by the session. If it doesn't get set + -- then core.get_model() will reset it to the default + state.current_model = nil state.active_session = selected_session if state.windows then state.restore_points = {} @@ -67,6 +70,8 @@ function M.open(opts) if opts.new_session then state.active_session = nil state.last_sent_context = nil + -- clear current_model here so it can be reset to the default (if one is set) + state.current_model = nil state.active_session = M.create_new_session() else if not state.active_session then @@ -107,7 +112,7 @@ function M.send_message(prompt, opts) opts.context = vim.tbl_deep_extend('force', state.current_context_config or {}, opts.context or {}) state.current_context_config = opts.context context.load() - opts.model = opts.model or state.current_model + opts.model = opts.model or M.initialize_current_model() opts.agent = opts.agent or state.current_mode or config.default_mode local params = {} @@ -325,6 +330,22 @@ function M.ensure_current_mode() return true end +---Initialize current model if it's not already set. +---@return string|nil The current model (or the default model, if configured) +function M.initialize_current_model() + if state.current_model then + return state.current_model + end + + local config_file = require('opencode.config_file').get_opencode_config() + + if config_file and config_file.model and config_file.model ~= '' then + state.current_model = config_file.model + end + + return state.current_model +end + function M.setup() state.subscribe('opencode_server', on_opencode_server) diff --git a/lua/opencode/state.lua b/lua/opencode/state.lua index 3ab00c34..f143e031 100644 --- a/lua/opencode/state.lua +++ b/lua/opencode/state.lua @@ -1,5 +1,3 @@ -local config = require('opencode.config') - ---@class OpencodeWindowState ---@field input_win integer|nil ---@field output_win integer|nil diff --git a/lua/opencode/ui/renderer.lua b/lua/opencode/ui/renderer.lua index 7ae113bf..527a7c3a 100644 --- a/lua/opencode/ui/renderer.lua +++ b/lua/opencode/ui/renderer.lua @@ -5,14 +5,14 @@ local output_window = require('opencode.ui.output_window') local Promise = require('opencode.promise') local RenderState = require('opencode.ui.render_state') -local M = {} - -M._subscriptions = {} -M._prev_line_count = 0 -M._render_state = RenderState.new() -M._last_part_formatted = { - part_id = nil, - formatted_data = nil --[[@as Output|nil]], +local M = { + _subscriptions = {}, + _prev_line_count = 0, + _render_state = RenderState.new(), + _last_part_formatted = { + part_id = nil, + formatted_data = nil --[[@as Output|nil]], + }, } local trigger_on_data_rendered = require('opencode.util').debounce(function() @@ -135,6 +135,10 @@ function M._render_full_session_data(session_data) -- local event_manager = state.event_manager + -- if we're loading a session and there's no currently selected model, set it + -- from the messages + local set_mode_from_messages = not state.current_model + for i, msg in ipairs(session_data) do if state.active_session.revert and state.active_session.revert.messageID == msg.info.id then revert_index = i @@ -153,6 +157,9 @@ function M._render_full_session_data(session_data) M._write_formatted_data(formatter._format_revert_message(state.messages, revert_index)) end + if set_mode_from_messages then + M._set_model_from_messages() + end M.scroll_to_bottom() end @@ -182,6 +189,25 @@ function M.on_emit_events_finished() M.scroll_to_bottom() end +---Find the most recently used model from the messages +function M._set_model_from_messages() + if not state.messages then + return + end + + for i = #state.messages, 1, -1 do + local message = state.messages[i] + + if message and message.info and message.info.modelID and message.info.providerID then + state.current_model = message.info.providerID .. '/' .. message.info.modelID + return + end + end + + -- we didn't find a model from any messages, set it to the default + require('opencode.core').initialize_current_model() +end + ---Auto-scroll to bottom if user was already at bottom ---Respects cursor position if user has scrolled up function M.scroll_to_bottom() @@ -919,14 +945,6 @@ function M.get_actions_for_line(line) return M._render_state:get_actions_at_line(line) end ----Update stats from all messages in session ----@param messages OpencodeMessage[] -function M._update_stats_from_messages(messages) - for _, msg in ipairs(messages) do - M._update_stats_from_message(msg) - end -end - ---Update display stats from a single message ---@param message OpencodeMessage function M._update_stats_from_message(message) diff --git a/lua/opencode/ui/topbar.lua b/lua/opencode/ui/topbar.lua index 9582a2c8..e360aeed 100644 --- a/lua/opencode/ui/topbar.lua +++ b/lua/opencode/ui/topbar.lua @@ -1,3 +1,4 @@ +local config = require('opencode.config') local util = require('opencode.util') local M = {} @@ -10,16 +11,10 @@ local LABELS = { } local function format_model_info() - if not state.current_model or state.current_model == '' then - local info = config_file.get_opencode_config() - state.current_model = info and info.model - end - - local config = require('opencode.config') local parts = {} - if config.ui.display_model and state.current_model then - if state.current_model ~= '' then + if config.ui.display_model then + if state.current_model then table.insert(parts, state.current_model) end end