Skip to content

Commit b4467a1

Browse files
authored
feat(deepseek): #692 #669 show reasoning output (#716)
1 parent 21b2adc commit b4467a1

File tree

2 files changed

+73
-10
lines changed

2 files changed

+73
-10
lines changed

lua/codecompanion/adapters/deepseek.lua

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,37 @@ return {
110110
end,
111111

112112
chat_output = function(self, data)
113-
return openai.handlers.chat_output(self, data)
113+
local output = {}
114+
115+
if data and data ~= "" then
116+
local data_mod = prepare_data_for_json(data)
117+
local ok, json = pcall(vim.json.decode, data_mod, { luanil = { object = true } })
118+
119+
if ok and json.choices and #json.choices > 0 then
120+
local choice = json.choices[1]
121+
local delta = (self.opts and self.opts.stream) and choice.delta or choice.message
122+
123+
if delta then
124+
output.role = nil
125+
if delta.role then
126+
output.role = delta.role
127+
end
128+
129+
if self.opts.can_reason and delta.reasoning_content then
130+
output.reasoning = delta.reasoning_content
131+
end
132+
133+
if delta.content then
134+
output.content = (output.content or "") .. delta.content
135+
end
136+
137+
return {
138+
status = "success",
139+
output = output,
140+
}
141+
end
142+
end
143+
end
114144
end,
115145
inline_output = function(self, data, context)
116146
return openai.handlers.inline_output(self, data, context)
@@ -128,7 +158,7 @@ return {
128158
---@type string|fun(): string
129159
default = "deepseek-reasoner",
130160
choices = {
131-
"deepseek-reasoner",
161+
["deepseek-reasoner"] = { opts = { can_reason = true } },
132162
"deepseek-chat",
133163
},
134164
},

lua/codecompanion/strategies/chat/init.lua

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,9 @@ end
8888

8989
---Parse the chat buffer for the last message
9090
---@param chat CodeCompanion.Chat
91-
---@param role string
9291
---@param start_range number
9392
---@return { content: string }
94-
local function ts_parse_messages(chat, role, start_range)
93+
local function ts_parse_messages(chat, start_range)
9594
local query = get_query("markdown", "chat")
9695

9796
local tree = chat.parser:parse({ start_range - 1, -1 })[1]
@@ -589,7 +588,7 @@ function Chat:submit(opts)
589588

590589
local bufnr = self.bufnr
591590

592-
local message = ts_parse_messages(self, user_role, self.header_line)
591+
local message = ts_parse_messages(self, self.header_line)
593592

594593
-- Check if any watched buffers have any changes
595594
self.watchers:check_for_changes(self)
@@ -860,6 +859,8 @@ function Chat:close()
860859
self = nil
861860
end
862861

862+
local has_been_reasoning = false
863+
863864
---Add a message directly to the chat buffer. This will be visible to the user
864865
---@param data table
865866
---@param opts? table
@@ -868,21 +869,42 @@ function Chat:add_buf_message(data, opts)
868869
local bufnr = self.bufnr
869870
local new_response = false
870871

871-
if (data.role and data.role ~= self.last_role) or (opts and opts.force_role) then
872+
local function write(text)
873+
for _, t in ipairs(vim.split(text, "\n", { plain = true, trimempty = false })) do
874+
table.insert(lines, t)
875+
end
876+
end
877+
878+
local function new_role()
872879
new_response = true
873880
self.last_role = data.role
874881
table.insert(lines, "")
875882
table.insert(lines, "")
876883
self.ui:set_header(lines, config.strategies.chat.roles[data.role])
877884
end
878885

879-
if data.content then
880-
for _, text in ipairs(vim.split(data.content, "\n", { plain = true, trimempty = false })) do
881-
table.insert(lines, text)
886+
local function append_data()
887+
if data.reasoning then
888+
has_been_reasoning = true
889+
if new_response then
890+
table.insert(lines, "### Reasoning")
891+
table.insert(lines, "")
892+
end
893+
write(data.reasoning)
894+
else
895+
if has_been_reasoning then
896+
has_been_reasoning = false
897+
table.insert(lines, "")
898+
table.insert(lines, "")
899+
table.insert(lines, "### Response")
900+
table.insert(lines, "")
901+
end
902+
write(data.content)
882903
end
904+
end
883905

906+
local function update_buffer()
884907
self.ui:unlock_buf()
885-
886908
local last_line, last_column, line_count = self.ui:last()
887909
if opts and opts.insert_at then
888910
last_line = opts.insert_at
@@ -906,6 +928,17 @@ function Chat:add_buf_message(data, opts)
906928
self.ui:follow()
907929
end
908930
end
931+
932+
-- Handle a new role
933+
if (data.role and data.role ~= self.last_role) or (opts and opts.force_role) then
934+
new_role()
935+
end
936+
937+
-- Append the output from the LLM
938+
if data.content or data.reasoning then
939+
append_data()
940+
update_buffer()
941+
end
909942
end
910943

911944
---When a request has finished, reset the chat buffer

0 commit comments

Comments
 (0)