2525--- @field private _contexts table Active contexts for this chat session
2626--- @field private _selected_code table Current selected code for display
2727--- @field private _todos table List of active todos
28+ --- @field private _current_status string Current processing status message
2829--- @field private _augroup integer Autocmd group ID
2930--- @field private _response_start_time number Timestamp when streaming started
3031--- @field private _max_response_length number Maximum allowed response length
@@ -49,6 +50,7 @@ function M:new(id)
4950 instance ._contexts = {}
5051 instance ._selected_code = nil
5152 instance ._todos = {}
53+ instance ._current_status = " "
5254 instance ._augroup = vim .api .nvim_create_augroup (" eca_sidebar_" .. id , { clear = true })
5355 instance ._response_start_time = 0
5456 instance ._max_response_length = 50000 -- 50KB max response
@@ -175,6 +177,7 @@ function M:reset()
175177 self ._contexts = {}
176178 self ._selected_code = nil
177179 self ._todos = {}
180+ self ._current_status = " "
178181end
179182
180183function M :new_chat ()
@@ -206,6 +209,7 @@ function M:_create_containers()
206209 -- Calculate dynamic heights using existing methods
207210 local input_height = Config .windows .input .height
208211 local usage_height = 1
212+ local status_height = 1
209213 local contexts_height = self :get_contexts_height ()
210214 local selected_code_height = self :get_selected_code_height ()
211215 local todos_height = self :get_todos_height ()
@@ -229,14 +233,36 @@ function M:_create_containers()
229233 winfixwidth = false ,
230234 }
231235
232- -- 1. Create and mount main chat container first
233- self .containers .chat = Split ({
236+ -- 1. Create and mount contexts container first (moved to top)
237+ self .containers .contexts = Split ({
234238 relative = " editor" ,
235239 position = " right" ,
236240 size = {
237241 width = width ,
238- height = chat_height ,
242+ height = contexts_height ,
243+ },
244+ buf_options = vim .tbl_deep_extend (" force" , base_buf_options , {
245+ modifiable = false ,
246+ }),
247+ win_options = vim .tbl_deep_extend (" force" , base_win_options , {
248+ winhighlight = " Normal:Comment" ,
249+ }),
250+ })
251+ self .containers .contexts :mount ()
252+ self :_setup_container_events (self .containers .contexts , " contexts" )
253+ Utils .debug (" Mounted container: contexts (winid: " .. self .containers .contexts .winid .. " )" )
254+
255+ -- Track the last mounted container winid for relative positioning
256+ local last_winid = self .containers .contexts .winid
257+
258+ -- 2. Create and mount main chat container below contexts
259+ self .containers .chat = Split ({
260+ relative = {
261+ type = " win" ,
262+ winid = last_winid ,
239263 },
264+ position = " bottom" ,
265+ size = { height = chat_height },
240266 buf_options = vim .tbl_deep_extend (" force" , base_buf_options , {
241267 modifiable = true ,
242268 filetype = " markdown" ,
@@ -245,12 +271,10 @@ function M:_create_containers()
245271 })
246272 self .containers .chat :mount ()
247273 self :_setup_container_events (self .containers .chat , " chat" )
248- Utils .debug (" Mounted container: chat (winid: " .. self .containers .chat .winid .. " )" )
249-
250- -- Track the last mounted container winid for relative positioning
251- local last_winid = self .containers .chat .winid
274+ last_winid = self .containers .chat .winid
275+ Utils .debug (" Mounted container: chat (winid: " .. last_winid .. " )" )
252276
253- -- 2 . Create selected_code container (conditional)
277+ -- 3 . Create selected_code container (conditional)
254278 if selected_code_height > 0 then
255279 self .containers .selected_code = Split ({
256280 relative = {
@@ -273,7 +297,7 @@ function M:_create_containers()
273297 Utils .debug (" Mounted container: selected_code (winid: " .. last_winid .. " )" )
274298 end
275299
276- -- 3 . Create todos container (conditional)
300+ -- 4 . Create todos container (conditional)
277301 if todos_height > 0 then
278302 self .containers .todos = Split ({
279303 relative = {
@@ -295,73 +319,74 @@ function M:_create_containers()
295319 Utils .debug (" Mounted container: todos (winid: " .. last_winid .. " )" )
296320 end
297321
298- -- 4 . Create contexts container (always present)
299- self .containers .contexts = Split ({
322+ -- 5 . Create status container (always present) - for processing messages
323+ self .containers .status = Split ({
300324 relative = {
301325 type = " win" ,
302326 winid = last_winid ,
303327 },
304328 position = " bottom" ,
305- size = { height = contexts_height },
329+ size = { height = status_height },
306330 buf_options = vim .tbl_deep_extend (" force" , base_buf_options , {
307331 modifiable = false ,
308332 }),
309333 win_options = vim .tbl_deep_extend (" force" , base_win_options , {
310- winhighlight = " Normal:Comment " ,
334+ winhighlight = " Normal:WarningMsg " ,
311335 }),
312336 })
313- self .containers .contexts :mount ()
314- self :_setup_container_events (self .containers .contexts , " contexts " )
315- last_winid = self .containers .contexts .winid
316- Utils .debug (" Mounted container: contexts (winid: " .. last_winid .. " )" )
337+ self .containers .status :mount ()
338+ self :_setup_container_events (self .containers .status , " status " )
339+ last_winid = self .containers .status .winid
340+ Utils .debug (" Mounted container: status (winid: " .. last_winid .. " )" )
317341
318- -- 5 . Create usage container (always present)
319- self .containers .usage = Split ({
342+ -- 6 . Create input container (always present)
343+ self .containers .input = Split ({
320344 relative = {
321345 type = " win" ,
322346 winid = last_winid ,
323347 },
324348 position = " bottom" ,
325- size = { height = usage_height },
349+ size = { height = input_height },
326350 buf_options = vim .tbl_deep_extend (" force" , base_buf_options , {
327- modifiable = false ,
351+ modifiable = true ,
328352 }),
329353 win_options = vim .tbl_deep_extend (" force" , base_win_options , {
330- winhighlight = " Normal:StatusLine" ,
331354 statusline = " " ,
332355 }),
333356 })
334- self .containers .usage :mount ()
335- self :_setup_container_events (self .containers .usage , " usage " )
336- last_winid = self .containers .usage .winid
337- Utils .debug (" Mounted container: usage (winid: " .. last_winid .. " )" )
357+ self .containers .input :mount ()
358+ self :_setup_container_events (self .containers .input , " input " )
359+ last_winid = self .containers .input .winid
360+ Utils .debug (" Mounted container: input (winid: " .. last_winid .. " )" )
338361
339- -- 6 . Create input container (always present)
340- self .containers .input = Split ({
362+ -- 7 . Create usage container (always present) - moved to bottom
363+ self .containers .usage = Split ({
341364 relative = {
342365 type = " win" ,
343366 winid = last_winid ,
344367 },
345368 position = " bottom" ,
346- size = { height = input_height },
369+ size = { height = usage_height },
347370 buf_options = vim .tbl_deep_extend (" force" , base_buf_options , {
348- modifiable = true ,
371+ modifiable = false ,
349372 }),
350373 win_options = vim .tbl_deep_extend (" force" , base_win_options , {
374+ winhighlight = " Normal:StatusLine" ,
351375 statusline = " " ,
352376 }),
353377 })
354- self .containers .input :mount ()
355- self :_setup_container_events (self .containers .input , " input " )
356- Utils .debug (" Mounted container: input (winid: " .. self .containers .input .winid .. " )" )
378+ self .containers .usage :mount ()
379+ self :_setup_container_events (self .containers .usage , " usage " )
380+ Utils .debug (" Mounted container: usage (winid: " .. self .containers .usage .winid .. " )" )
357381
358- Utils .debug (string.format (" Created containers: chat=%d, selected_code=%s, todos=%s, contexts=%d, usage=%d, input=%d" ,
382+ Utils .debug (string.format (" Created containers: contexts=%d, chat=%d, selected_code=%s, todos=%s, status=%d, input=%d, usage=%d" ,
383+ contexts_height ,
359384 chat_height ,
360385 selected_code_height > 0 and tostring (selected_code_height ) or " hidden" ,
361386 todos_height > 0 and tostring (todos_height ) or " hidden" ,
362- contexts_height ,
363- usage_height ,
364- input_height ))
387+ status_height ,
388+ input_height ,
389+ usage_height ))
365390end
366391
367392--- @private
@@ -391,6 +416,8 @@ function M:_setup_container_events(container, name)
391416 self :_setup_todos_keymaps (container )
392417 elseif name == " input" then
393418 self :_setup_input_keymaps (container )
419+ elseif name == " status" then
420+ -- No special keymaps for status container (read-only)
394421 end
395422end
396423
@@ -449,12 +476,13 @@ function M:_update_container_sizes()
449476
450477 -- Recalculate heights
451478 local new_heights = {
479+ contexts = self :get_contexts_height (),
452480 chat = self :get_chat_height (),
453481 selected_code = self :get_selected_code_height (),
454482 todos = self :get_todos_height (),
455- contexts = self :get_contexts_height (),
456- usage = 1 ,
483+ status = 1 ,
457484 input = Config .windows .input .height ,
485+ usage = 1 ,
458486 }
459487
460488 -- Update container sizes
@@ -507,12 +535,13 @@ function M:get_chat_height()
507535 local total_height = vim .o .lines - vim .o .cmdheight - 1
508536 local input_height = Config .windows .input .height
509537 local usage_height = 1
538+ local status_height = 1
510539 local contexts_height = self :get_contexts_height ()
511540 local selected_code_height = self :get_selected_code_height ()
512541 local todos_height = self :get_todos_height ()
513542
514543 return math.max (10 ,
515- total_height - input_height - usage_height - contexts_height
544+ total_height - input_height - usage_height - status_height - contexts_height
516545 - selected_code_height - todos_height - 3
517546 )
518547end
621650
622651function M :_setup_containers ()
623652 -- Setup each container's content and behavior
653+ self :_setup_contexts_container ()
624654 self :_setup_chat_container ()
625655
626656 if self .containers .selected_code then
@@ -631,15 +661,19 @@ function M:_setup_containers()
631661 self :_setup_todos_container ()
632662 end
633663
634- self :_setup_contexts_container ()
635- self :_setup_usage_container ()
664+ self :_setup_status_container ()
636665 self :_setup_input_container ()
666+ self :_setup_usage_container ()
637667
638668 self ._initialized = true
639669end
640670
641671function M :_refresh_container_content ()
642672 -- Refresh content without full setup
673+ if self .containers .contexts then
674+ self :_update_contexts_display ()
675+ end
676+
643677 if self .containers .chat then
644678 self :_set_welcome_content ()
645679 end
@@ -652,17 +686,17 @@ function M:_refresh_container_content()
652686 self :_update_todos_display ()
653687 end
654688
655- if self .containers .contexts then
656- self :_update_contexts_display ()
657- end
658-
659- if self .containers .usage then
660- self :_update_usage_info (self ._usage_info )
689+ if self .containers .status then
690+ self :_update_status_display ()
661691 end
662692
663693 if self .containers .input then
664694 self :_add_input_line ()
665695 end
696+
697+ if self .containers .usage then
698+ self :_update_usage_info (self ._usage_info )
699+ end
666700end
667701
668702-- Placeholder for all the other methods from original sidebar
@@ -722,6 +756,14 @@ function M:_setup_contexts_container()
722756 self :_update_contexts_display ()
723757end
724758
759+ function M :_setup_status_container ()
760+ local status = self .containers .status
761+ if not status then return end
762+
763+ -- Set initial status display
764+ self :_update_status_display ()
765+ end
766+
725767function M :_setup_usage_container ()
726768 local usage = self .containers .usage
727769 if not usage then return end
@@ -993,6 +1035,29 @@ function M:_update_contexts_display()
9931035 vim .api .nvim_set_option_value (" modifiable" , false , { buf = contexts .bufnr })
9941036end
9951037
1038+ function M :_update_status_display ()
1039+ local status = self .containers .status
1040+ if not status or not vim .api .nvim_buf_is_valid (status .bufnr ) then
1041+ return
1042+ end
1043+
1044+ local status_text = self ._current_status or " "
1045+ if status_text == " " then
1046+ status_text = " 💤 Ready"
1047+ end
1048+
1049+ -- Update the buffer
1050+ vim .api .nvim_set_option_value (" modifiable" , true , { buf = status .bufnr })
1051+ vim .api .nvim_buf_set_lines (status .bufnr , 0 , - 1 , false , { status_text })
1052+ vim .api .nvim_set_option_value (" modifiable" , false , { buf = status .bufnr })
1053+ end
1054+
1055+ --- @param status_text string
1056+ function M :set_status (status_text )
1057+ self ._current_status = status_text or " "
1058+ self :_update_status_display ()
1059+ end
1060+
9961061function M :_update_usage_info (usage_text )
9971062 local usage = self .containers .usage
9981063 if not usage or not vim .api .nvim_buf_is_valid (usage .bufnr ) then
@@ -1066,9 +1131,11 @@ function M:_handle_server_content(params)
10661131 self :_handle_streaming_text (content .text )
10671132 elseif content .type == " progress" then
10681133 if content .state == " running" then
1069- self :_add_message (" assistant" , " ⏳ " .. (content .text or " Processing..." ))
1134+ -- Show progress in status container instead of chat
1135+ self :set_status (" ⏳ " .. (content .text or " Processing..." ))
10701136 elseif content .state == " finished" then
1071- -- Finalize any streaming response and prepare for next input
1137+ -- Clear status and finalize any streaming response
1138+ self :set_status (" 💤 Ready" )
10721139 self :_finalize_streaming_response ()
10731140 self :_add_input_line ()
10741141 end
0 commit comments