2024-05-03 01:22:56 +02:00
|
|
|
local VERSION = "2023-06-01"
|
2024-05-06 15:46:38 +02:00
|
|
|
-- local USERAGENT = "anthropic.nvim/0.0.0"
|
|
|
|
|
2024-05-03 01:22:56 +02:00
|
|
|
local opts = require("anthropic").opts
|
|
|
|
|
|
|
|
local M = {}
|
|
|
|
|
|
|
|
--- # Make headers for an anthropic API call
|
|
|
|
---
|
|
|
|
--- This will generate the base anthropic API headers
|
|
|
|
---@return table<string, string>? headers # The headers
|
|
|
|
function M.make_headers()
|
|
|
|
if not opts.token then
|
2024-05-04 21:12:31 +02:00
|
|
|
vim.notify("anthropic: no API key provided in opts", vim.log.levels.ERROR)
|
2024-05-03 01:22:56 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2024-05-06 15:46:38 +02:00
|
|
|
local headers = {
|
|
|
|
-- ["user-agent"] = USERAGENT,
|
|
|
|
["content-type"] = "application/json",
|
|
|
|
["anthropic-version"] = VERSION,
|
|
|
|
["x-api-key"] = opts.token,
|
|
|
|
}
|
2024-05-03 01:22:56 +02:00
|
|
|
|
|
|
|
return headers
|
|
|
|
end
|
|
|
|
|
|
|
|
--- # Make message request for anthropic
|
|
|
|
---
|
|
|
|
--- This will generate the json body for an anthropic message call
|
2024-05-04 20:32:00 +02:00
|
|
|
---@param session session
|
2024-05-03 01:22:56 +02:00
|
|
|
---@param model string?
|
|
|
|
---@param max_tokens integer?
|
|
|
|
---@param system string?
|
|
|
|
---@param temperature float?
|
|
|
|
---@param top_k integer?
|
|
|
|
---@param top_p integer?
|
|
|
|
---@return table<string, any>?
|
2024-05-04 20:32:00 +02:00
|
|
|
function M.make_body(session, model, max_tokens, system, temperature, top_k, top_p)
|
2024-05-03 01:22:56 +02:00
|
|
|
model = model or "claude-3-sonnet-20240229"
|
|
|
|
max_tokens = max_tokens or 1024
|
|
|
|
|
|
|
|
return {
|
2024-05-04 20:32:00 +02:00
|
|
|
messages = session,
|
2024-05-03 01:22:56 +02:00
|
|
|
model = model,
|
|
|
|
max_tokens = max_tokens,
|
|
|
|
system = system,
|
|
|
|
temperature = temperature,
|
|
|
|
top_k = top_k,
|
|
|
|
top_p = top_p,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
--- # Curl exit code test
|
|
|
|
---
|
|
|
|
--- Tests the curl exit code and notifies the user if something went wrong.
|
|
|
|
---@param exit_code integer
|
|
|
|
---@return boolean
|
|
|
|
function M.test_code(exit_code)
|
|
|
|
if exit_code == 127 then
|
2024-05-04 20:32:00 +02:00
|
|
|
vim.notify("anthropic: couldn't find curl binary in path", vim.log.levels.ERROR)
|
2024-05-03 01:22:56 +02:00
|
|
|
return false
|
|
|
|
elseif exit_code ~= 0 then
|
2024-05-04 20:32:00 +02:00
|
|
|
vim.notify("anthropic: unkown curl exit code: " .. exit_code, vim.log.levels.ERROR)
|
2024-05-03 01:22:56 +02:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
--- # Curl callback
|
|
|
|
---
|
|
|
|
--- This function wraps the callback passed to transfarmer.util.call to perform
|
2024-05-04 20:32:00 +02:00
|
|
|
--- error checking and json decoding
|
2024-05-03 01:22:56 +02:00
|
|
|
---@param response curl_response
|
|
|
|
---@param callback curl_callback
|
|
|
|
local function callback_wrapper(response, callback)
|
|
|
|
if response.status ~= 200 then
|
|
|
|
response.body = response.body:gsub("%s+", " ")
|
|
|
|
print("Error: " .. response.status .. " " .. response.body)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if response.body == nil or response.body == "" then
|
2024-05-04 20:32:00 +02:00
|
|
|
vim.notify("anthropic: empty response body", vim.log.levels.ERROR)
|
2024-05-03 01:22:56 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
vim.schedule_wrap(function(body)
|
|
|
|
local ok, result = pcall(vim.fn.json_decode, body)
|
|
|
|
if ok then
|
|
|
|
callback(result)
|
|
|
|
else
|
2024-05-04 20:32:00 +02:00
|
|
|
vim.notify("anthropic: failed to decode json: " .. result, vim.log.levels.ERROR)
|
2024-05-03 01:22:56 +02:00
|
|
|
end
|
|
|
|
end)(response.body)
|
|
|
|
end
|
|
|
|
|
|
|
|
--- # Call a anthropic's API
|
|
|
|
---
|
|
|
|
--- This function calls the API with the given payload and passes the decoded
|
|
|
|
--- json response to the callback function.
|
|
|
|
---@param payload table<string, any>
|
|
|
|
---@param callback fun(decoded: table<string, any>): nil
|
|
|
|
function M.call(payload, callback)
|
|
|
|
local payload_str = vim.fn.json_encode(payload)
|
|
|
|
local url = opts.api_url
|
|
|
|
local headers = M.make_headers()
|
|
|
|
|
|
|
|
require("plenary.curl").post(url, {
|
|
|
|
body = payload_str,
|
|
|
|
headers = headers,
|
|
|
|
callback = function(response)
|
|
|
|
callback_wrapper(response, callback)
|
|
|
|
end,
|
|
|
|
on_error = function(err)
|
2024-05-04 20:32:00 +02:00
|
|
|
vim.notify("anthropic: curl error from: " .. err.message, vim.log.levels.WARNING)
|
2024-05-03 01:22:56 +02:00
|
|
|
end,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
return M
|