@@ -25,6 +25,8 @@ local Split = require("nui.split")
2525--- @field private _augroup integer Autocmd group ID
2626--- @field private _response_start_time number Timestamp when streaming started
2727--- @field private _max_response_length number Maximum allowed response length
28+ --- @field private _headers table Table of headers for the chat
29+
2830local M = {}
2931M .__index = M
3032
@@ -58,6 +60,10 @@ function M.new(id, mediator)
5860 instance ._augroup = vim .api .nvim_create_augroup (" eca_sidebar_" .. id , { clear = true })
5961 instance ._response_start_time = 0
6062 instance ._max_response_length = 50000 -- 50KB max response
63+ instance ._headers = {
64+ user = (Config .chat and Config .chat .headers and Config .chat .headers .user ) or " ## 👤 You\n\n " ,
65+ assistant = (Config .chat and Config .chat .headers and Config .chat .headers .assistant ) or " ## 🤖 ECA\n\n " ,
66+ }
6167
6268 require (" eca.observer" ).subscribe (id , function (message )
6369 instance :handle_chat_content (message )
@@ -874,6 +880,7 @@ function M:_set_welcome_content()
874880 " - **RepoMap**: Use `:EcaAddRepoMap` to add repository structure context" ,
875881 " " ,
876882 " ---" ,
883+ " "
877884 }
878885
879886 Logger .debug (" Setting welcome content for new chat" )
@@ -1161,6 +1168,9 @@ function M:_send_message(message)
11611168 -- Store the last user message to avoid duplication
11621169 self ._last_user_message = message
11631170
1171+ -- Add user message to chat
1172+ self :_add_message (" user" , message )
1173+
11641174 local contexts = self :get_contexts ()
11651175 self .mediator :send (" chat/prompt" , {
11661176 chatId = self .id ,
@@ -1268,11 +1278,16 @@ end
12681278function M :_handle_streaming_text (text )
12691279 -- Only check for empty text
12701280 if not text or text == " " then
1271- Logger .trace (" Ignoring empty text response" )
1281+ Logger .debug (" Ignoring empty text response" )
12721282 return
12731283 end
12741284 Logger .debug (" Received text chunk: '" .. text :sub (1 , 50 ) .. (text :len () > 50 and " ..." or " " ) .. " '" )
12751285
1286+ if vim .trim (text ) == vim .trim (self ._last_user_message ) then
1287+ Logger .debug (" Ignoring duplicate user message in response" )
1288+ return
1289+ end
1290+
12761291 if not self ._is_streaming then
12771292 Logger .debug (" Starting streaming response" )
12781293 -- Start streaming - simple and direct
@@ -1311,10 +1326,13 @@ function M:_update_streaming_message(content)
13111326 -- Make buffer modifiable
13121327 vim .api .nvim_set_option_value (" modifiable" , true , { buf = chat .bufnr })
13131328
1329+ -- Concat content with header
1330+ content = self ._headers .assistant .. content
1331+
13141332 -- Get current lines
13151333 local lines = vim .api .nvim_buf_get_lines (chat .bufnr , 0 , - 1 , false )
13161334 local content_lines = Utils .split_lines (content )
1317- local start_line = self ._last_assistant_line + 2 -- Skip "## 🤖 ECA" and empty line
1335+ local start_line = self ._last_assistant_line
13181336
13191337 Logger .debug (" DEBUG: Assistant line: " .. self ._last_assistant_line .. " , start_line: " .. start_line )
13201338 Logger .debug (" DEBUG: Content lines: " .. # content_lines )
@@ -1359,22 +1377,16 @@ function M:_add_message(role, content)
13591377
13601378 self :_safe_buffer_update (chat .bufnr , function ()
13611379 local lines = vim .api .nvim_buf_get_lines (chat .bufnr , 0 , - 1 , false )
1380+ local header = " "
13621381
1363- -- Add separator if not the first message
1364- if # lines > 0 and lines [# lines ] ~= " " then
1365- table.insert (lines , " " )
1366- table.insert (lines , " ---" )
1367- table.insert (lines , " " )
1368- end
1369-
1370- -- Add role header with better markdown formatting
13711382 if role == " user" then
1372- table.insert ( lines , " ## 👤 You " )
1373- else
1374- table.insert ( lines , " ## 🤖 ECA " )
1383+ header = self . _headers . user
1384+ elseif role == " assistant " then
1385+ header = self . _headers . assistant
13751386 end
13761387
1377- table.insert (lines , " " )
1388+ -- Concat header and content
1389+ content = header .. content
13781390
13791391 -- Add content with better markdown formatting
13801392 local content_lines = Utils .split_lines (content )
@@ -1402,7 +1414,9 @@ function M:_add_message(role, content)
14021414 end
14031415 end
14041416
1405- table.insert (lines , " " )
1417+ if content ~= " " then
1418+ table.insert (lines , " " )
1419+ end
14061420
14071421 -- Update buffer safely
14081422 vim .api .nvim_buf_set_lines (chat .bufnr , 0 , - 1 , false , lines )
@@ -1461,8 +1475,19 @@ function M:_get_last_message_line()
14611475 end
14621476
14631477 local lines = vim .api .nvim_buf_get_lines (chat .bufnr , 0 , - 1 , false )
1478+ local assistant_header_lines = Utils .split_lines (self ._headers .assistant )
1479+ local assistant_header = " "
1480+
1481+ for i = # assistant_header_lines , 1 , - 1 do
1482+ if assistant_header_lines [i ] and assistant_header_lines [i ] ~= " " then
1483+ assistant_header = assistant_header_lines [i ]
1484+ break
1485+ end
1486+ end
1487+
14641488 for i = # lines , 1 , - 1 do
1465- if lines [i ] and lines [i ]:match (" ^## 🤖 ECA" ) then
1489+ local line = lines [i ]
1490+ if line and line :sub (1 , # assistant_header ) == assistant_header then
14661491 return i
14671492 end
14681493 end
0 commit comments