Repository navigation
|
I'm a bit stuck implementing a custom adapter for the HAWKI API. My current draft heavily inspired by the DashScope Community Adapter: tudagpt = function()
local log = require "codecompanion.utils.log"
local openai = require "codecompanion.adapters.http.openai"
local utils = require "codecompanion.adapters.utils"
---@class CodeCompanion.HTTPAdapter.DashScope: CodeCompanion.HTTPAdapter
return {
name = "tudagpt",
formatted_name = "TUDaGPT",
roles = {
llm = "assistant",
user = "user",
},
opts = {
stream = false,
tools = false,
},
features = {
text = true,
tokens = true,
},
url = "${url}${chat_url}",
env = {
url = "https://tudagpt.hrz.tu-darmstadt.de",
api_key = "cmd:secret-tool lookup tudagpt codecompanion",
chat_url = "/api/ai-req",
},
headers = {
["Authorization"] = "Bearer ${api_key}",
["Content-Type"] = "application/json",
},
handlers = {
-- Lifecycle hooks (side effects and initialization)
lifecycle = {
setup = function(self) -- Called before request is sent
return openai.handlers.setup(self)
end,
on_exit = function(self, data) -- Called after request completes
return openai.handlers.on_exit(self, data)
end,
},
-- Request builders (pure transformations)
request = {
-- identical to openai `form_parameters`
build_parameters = function(self, params, messages)
return params
end,
build_messages = function(self, messages) -- Format messages for LLM
messages = utils.merge_messages(messages)
messages = utils.merge_system_messages(messages)
-- Ensure that all messages have a content field
messages = vim.iter(messages)
:map(function(msg)
local content = msg.content
if content and type(content) == "table" then
msg.content = table.concat(content, "\n")
elseif not content then
msg.content = ""
end
return msg
end)
:totable()
return { messages = messages }
end,
build_tools = function(self, tools) -- Transform tool schemas
local model = self.schema.model.default
local model_opts = self.schema.model.choices[model]
if model_opts.opts and model_opts.opts.can_use_tools == false then
if tools and vim.tbl_count(tools) > 0 then
log:warn "Tools are not supported for this model"
end
return
end
return openai.handlers.form_tools(self, tools)
end,
},
-- Response parsers (pure transformations)
response = {
parse_chat = function(self, data, tools) -- Parse chat response
local output = {}
if data and data ~= "" then
local data_mod = utils.clean_streamed_data(data)
local ok, json =
pcall(vim.json.decode, data_mod, { luanil = { object = true } })
if ok and json.choices and #json.choices > 0 then
local choice = json.choices[1]
local delta = (self.opts and self.opts.stream) and choice.delta
or choice.message
if delta then
output.role = delta.role
output.content = delta.content
if delta.reasoning_content then
output.reasoning = output.reasoning or {}
output.reasoning.content = delta.reasoning_content
end
-- Process tools
if self.opts.tools and delta.tool_calls and tools then
for _, tool in ipairs(delta.tool_calls) do
if self.opts.stream then
local index = tool.index
local found = false
for i, existing_tool in ipairs(tools) do
if existing_tool._index == index then
tools[i]["function"].arguments = (
tools[i]["function"].arguments or ""
)
.. (tool["function"]["arguments"] or "")
found = true
break
end
end
if not found then
table.insert(tools, {
["function"] = {
name = tool["function"]["name"],
arguments = tool["function"]["arguments"]
or "",
},
id = tool.id,
type = "function",
_index = index,
})
end
else
table.insert(tools, {
_index = tool.index,
["function"] = {
name = tool["function"]["name"],
arguments = tool["function"]["arguments"],
},
id = tool.id,
type = "function",
})
end
end
end
return {
status = "success",
output = output,
}
end
end
end
end,
parse_inline = function(self, data, context) -- Parse inline response
return openai.handlers.inline_output(self, data, context)
end,
parse_tokens = function(self, data) -- Extract token count
return openai.handlers.tokens(self, data)
end,
},
-- Tool handlers (grouped functionality)
tools = {
format_calls = function(self, tools) -- Format tool calls for request
return tools
end,
format_response = function(self, tool_call, output) -- Format tool response for LLM
return openai.handlers.tools.output_response(self, tool_call, output)
end,
},
},
schema = {
---@type CodeCompanion.Schema
model = {
order = 1,
mapping = "parameters",
type = "enum",
desc = "ID of the model to use.",
---@type string|fun(): string
default = "gwdg-meta-llama-3.1-8b-instruct",
choices = {
["gwdg-meta-llama-3.1-8b-instruct"] = {
formatted_name = "Meta LLama",
opts = { can_reason = false, can_use_tools = false },
},
},
},
...
},
}
endI get the following error: This differs from the error if use the curl example with an invalid token, which returns Do you have any tips how I can approach this problem or can you spot the faulty lines right away? Thank you for your help :) |
Answered by
olimorris
Sep 15, 2026
Replies: 1 comment 2 replies
|
My advice would be to use the |
2 replies
Answer selected by
KobKobson
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My advice would be to use the
search_helptool, sharing it with an LLM and the documentation from HAWKI. A Sonnet-5 equivalent model should be able to one-shot it.