@@ -154,6 +154,92 @@ describe('format_message', function()
154154 BaseContext .get_current_selection = original_get_current_selection
155155 BaseContext .get_current_file_for_selection = original_get_current_file_for_selection
156156 end )
157+
158+ it (' does not include current_file when disabled even if stale current_file exists' , function ()
159+ local ChatContext = require (' opencode.context.chat_context' )
160+ local BaseContext = require (' opencode.context.base_context' )
161+
162+ local original_get_current_buf = BaseContext .get_current_buf
163+ local original_get_diagnostics = BaseContext .get_diagnostics
164+
165+ ChatContext .context .current_file = {
166+ path = ' /tmp/foo.lua' ,
167+ name = ' foo.lua' ,
168+ extension = ' lua' ,
169+ sent_at = nil ,
170+ sent_at_mtime = nil ,
171+ }
172+
173+ BaseContext .get_current_buf = function ()
174+ return 1 , 1
175+ end
176+ BaseContext .get_diagnostics = function ()
177+ return {}
178+ end
179+
180+ local parts = context
181+ .format_message (' follow-up prompt' , {
182+ current_file = { enabled = false },
183+ selection = { enabled = false },
184+ diagnostics = { enabled = false },
185+ cursor_data = { enabled = false },
186+ buffer = { enabled = false },
187+ git_diff = { enabled = false },
188+ })
189+ :wait ()
190+
191+ local has_file_part = false
192+ for _ , part in ipairs (parts ) do
193+ if part .type == ' file' then
194+ has_file_part = true
195+ break
196+ end
197+ end
198+
199+ assert .is_false (has_file_part )
200+ assert .is_nil (ChatContext .context .current_file .sent_at )
201+
202+ BaseContext .get_current_buf = original_get_current_buf
203+ BaseContext .get_diagnostics = original_get_diagnostics
204+ end )
205+ end )
206+
207+ describe (' context update notifications' , function ()
208+ local ChatContext
209+ local original_now
210+
211+ before_each (function ()
212+ ChatContext = require (' opencode.context.chat_context' )
213+ ChatContext .context .mentioned_files = { ' /tmp/a.lua' }
214+ ChatContext .context .selections = { { file = { path = ' /tmp/a.lua' }, lines = ' 1, 1' , content = ' x' } }
215+ ChatContext .context .mentioned_subagents = { ' agent1' }
216+
217+ state .context_updated_at = 0
218+ local tick = 0
219+ original_now = vim .uv .now
220+ vim .uv .now = function ()
221+ tick = tick + 1
222+ return tick
223+ end
224+ end )
225+
226+ after_each (function ()
227+ vim .uv .now = original_now
228+ end )
229+
230+ it (' updates context_updated_at for clear operations and unload_attachments' , function ()
231+ ChatContext .clear_files ()
232+ assert .equal (1 , state .context_updated_at )
233+
234+ ChatContext .clear_selections ()
235+ assert .equal (2 , state .context_updated_at )
236+
237+ ChatContext .clear_subagents ()
238+ assert .equal (3 , state .context_updated_at )
239+
240+ context .unload_attachments ()
241+ assert .equal (4 , state .context_updated_at )
242+ end )
157243end )
158244
159245describe (' delta_context' , function ()
@@ -812,6 +898,53 @@ describe('ChatContext.load() preserves selections on file switch', function()
812898 BaseContext .new_selection = original_new_selection
813899 ChatContext .get_diagnostics = original_get_diagnostics
814900 end )
901+
902+ it (' should clear stale current_file when current_file context is disabled' , function ()
903+ ChatContext .context .current_file = {
904+ path = ' /tmp/stale.lua' ,
905+ name = ' stale.lua' ,
906+ extension = ' lua' ,
907+ sent_at = nil ,
908+ sent_at_mtime = nil ,
909+ }
910+
911+ local original_get_current_buf = BaseContext .get_current_buf
912+ local original_get_current_file = BaseContext .get_current_file
913+ local original_get_current_cursor_data = BaseContext .get_current_cursor_data
914+ local original_is_context_enabled = BaseContext .is_context_enabled
915+ local original_get_current_selection = BaseContext .get_current_selection
916+ local original_get_diagnostics = ChatContext .get_diagnostics
917+
918+ BaseContext .get_current_buf = function ()
919+ return 1 , 1
920+ end
921+ BaseContext .get_current_file = function ()
922+ return nil
923+ end
924+ BaseContext .get_current_cursor_data = function ()
925+ return nil
926+ end
927+ BaseContext .is_context_enabled = function ()
928+ return false
929+ end
930+ BaseContext .get_current_selection = function ()
931+ return nil
932+ end
933+ ChatContext .get_diagnostics = function ()
934+ return {}
935+ end
936+
937+ ChatContext .load ()
938+
939+ assert .is_nil (ChatContext .context .current_file )
940+
941+ BaseContext .get_current_buf = original_get_current_buf
942+ BaseContext .get_current_file = original_get_current_file
943+ BaseContext .get_current_cursor_data = original_get_current_cursor_data
944+ BaseContext .is_context_enabled = original_is_context_enabled
945+ BaseContext .get_current_selection = original_get_current_selection
946+ ChatContext .get_diagnostics = original_get_diagnostics
947+ end )
815948end )
816949
817950describe (' add_visual_selection API' , function ()
0 commit comments