Skip to content

Commit 7a77871

Browse files
committed
refactor: use OpenAI handler with parse_extra for DeepSeek adapter and add test
1 parent 7b9b42d commit 7a77871

File tree

3 files changed

+57
-68
lines changed

3 files changed

+57
-68
lines changed

lua/codecompanion/adapters/http/deepseek.lua

Lines changed: 8 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -94,73 +94,15 @@ return {
9494
---@param tools? table The table to write any tool output to
9595
---@return { status: string, output: { role: string, content: string, reasoning: string? } } | nil
9696
chat_output = function(self, data, tools)
97-
local output = {}
98-
99-
if data and data ~= "" then
100-
local data_mod = adapter_utils.clean_streamed_data(data)
101-
local ok, json = pcall(vim.json.decode, data_mod, { luanil = { object = true } })
102-
103-
if ok and json.choices and #json.choices > 0 then
104-
local choice = json.choices[1]
105-
local delta = (self.opts and self.opts.stream) and choice.delta or choice.message
106-
107-
if delta then
108-
output.role = delta.role
109-
output.content = delta.content
110-
111-
if delta.reasoning_content then
112-
output.reasoning = output.reasoning or {}
113-
output.reasoning.content = delta.reasoning_content
114-
end
115-
116-
-- Process tools
117-
if self.opts.tools and delta.tool_calls and tools then
118-
for _, tool in ipairs(delta.tool_calls) do
119-
if self.opts.stream then
120-
local index = tool.index
121-
local found = false
122-
123-
for i, existing_tool in ipairs(tools) do
124-
if existing_tool._index == index then
125-
tools[i]["function"].arguments = (tools[i]["function"].arguments or "")
126-
.. (tool["function"]["arguments"] or "")
127-
found = true
128-
break
129-
end
130-
end
131-
132-
if not found then
133-
table.insert(tools, {
134-
["function"] = {
135-
name = tool["function"]["name"],
136-
arguments = tool["function"]["arguments"] or "",
137-
},
138-
id = tool.id,
139-
type = "function",
140-
_index = index,
141-
})
142-
end
143-
else
144-
table.insert(tools, {
145-
_index = tool.index,
146-
["function"] = {
147-
name = tool["function"]["name"],
148-
arguments = tool["function"]["arguments"],
149-
},
150-
id = tool.id,
151-
type = "function",
152-
})
153-
end
154-
end
155-
end
156-
157-
return {
158-
status = "success",
159-
output = output,
160-
}
161-
end
162-
end
97+
return openai.handlers.chat_output(self, data, tools)
98+
end,
99+
parse_extra = function(self, data)
100+
local extra = data.extra
101+
if extra.reasoning_content then
102+
data.output.reasoning = { content = extra.reasoning_content }
103+
data.output.content = nil
163104
end
105+
return data
164106
end,
165107
inline_output = function(self, data, context)
166108
return openai.handlers.inline_output(self, data, context)

test_json.lua

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
local jsonschema = require("jsonschema")
2+
local schema = {
3+
type = "object",
4+
properties = {
5+
command = {
6+
type = "string",
7+
enum = { "query", "ls" },
8+
description = "Action to perform: 'query' for semantic search or 'ls' to list projects",
9+
},
10+
options = {
11+
type = "object",
12+
properties = {
13+
query = {
14+
type = "array",
15+
items = { type = "string" },
16+
description = "Query messages used for the search.",
17+
},
18+
count = {
19+
type = "integer",
20+
description = "Number of documents to retrieve, must be positive",
21+
},
22+
project_root = {
23+
type = "string",
24+
description = "Project path to search within (must be from 'ls' results)",
25+
},
26+
},
27+
required = { "query" },
28+
additionalProperties = false,
29+
},
30+
},
31+
required = { "command" },
32+
additionalProperties = false,
33+
}
34+
35+
local args = { {
36+
command = "query",
37+
options = { query = { "hi" } },
38+
}, { command = "ls" }, { command = "fhdsaif" } }
39+
40+
local validator = jsonschema.generate_validator(schema)
41+
for _, arg in pairs(args) do
42+
local res, err = validator(arg, schema)
43+
vim.notify(vim.inspect({ args = arg, result = res, error = err }))
44+
end

tests/adapters/http/test_deepseek.lua

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ T["DeepSeek adapter"]["Streaming"]["can handle reasoning content when streaming"
200200
local lines = vim.fn.readfile("tests/adapters/http/stubs/deepseek_streaming.txt")
201201
for _, line in ipairs(lines) do
202202
local chat_output = adapter.handlers.chat_output(adapter, line)
203+
if adapter.handlers.parse_extra and chat_output.extra then
204+
chat_output = adapter.handlers.parse_extra(adapter, chat_output)
205+
end
203206
if chat_output then
204207
if chat_output.output.reasoning and chat_output.output.reasoning.content then
205208
output.reasoning.content = output.reasoning.content .. chat_output.output.reasoning.content
@@ -277,7 +280,7 @@ T["DeepSeek adapter"]["No Streaming"]["can process tools"] = function()
277280

278281
local tool_output = {
279282
{
280-
_index = 0,
283+
_index = 1,
281284
["function"] = {
282285
arguments = '{"location": "London", "units": "celsius"}',
283286
name = "weather",
@@ -286,7 +289,7 @@ T["DeepSeek adapter"]["No Streaming"]["can process tools"] = function()
286289
type = "function",
287290
},
288291
{
289-
_index = 1,
292+
_index = 2,
290293
["function"] = {
291294
arguments = '{"location": "Paris", "units": "celsius"}',
292295
name = "weather",

0 commit comments

Comments
 (0)