diff --git a/README.md b/README.md index afea232..c93d2b2 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,18 @@ Features may be incomplete, bugs are likely to occur and breaking changes may oc # Configuration -no configuration currently. +You can configure the plugin to use OpenRouter (an OpenAI-compatible proxy) by passing options to `setup`: + +```lua +require('nes').setup({ + provider = 'openrouter', -- 'copilot' (default) or 'openrouter' + api_key = 'YOUR_OPENROUTER_API_KEY', -- required for openrouter + base_url = 'https://api.openrouter.ai/v1', -- optional, default "https://api.openrouter.ai/v1" + model = 'gpt-3.5-turbo', -- optional, default "gpt-3.5-turbo" for openrouter, "copilot-nes-v" for copilot +}) +``` + +Leave `provider = 'copilot'` (or omit `provider`) to use GitHub Copilot. # Usage diff --git a/lua/nes/api.lua b/lua/nes/api.lua index f12ec9d..89100ed 100644 --- a/lua/nes/api.lua +++ b/lua/nes/api.lua @@ -62,6 +62,66 @@ local function get_api_token() end function M.call(payload, callback) + local pkg = require("nes") + local opts = pkg.opts or {} + if opts.provider == "openrouter" then + local api_key = opts.api_key or vim.env.OPENROUTER_API_KEY + if not api_key then + error("OpenRouter API key not found") + end + local base_url = opts.base_url + or vim.env.OPENROUTER_API_BASE_URL + or "https://openrouter.ai/api/v1/chat/completions" + local open_payload = { + model = opts.model or "gpt-3.5-turbo", + messages = payload.messages, + temperature = payload.temperature, + top_p = payload.top_p, + n = payload.n, + stream = true, + } + local output = "" + + curl.post(base_url, { + + headers = { + ["Content-Type"] = "application/json", + ["Authorization"] = "Bearer " .. api_key, + }, + on_error = function(err) + error("openrouter request error: " .. err) + end, + body = vim.json.encode(open_payload), + stream = function(_, chunk) + if not chunk then + return + end + if vim.startswith(chunk, "data: ") then + chunk = chunk:sub(6) + end + if chunk == "[DONE]" then + return + end + local ok, event = pcall(vim.json.decode, chunk) + if not ok then + return + end + if event and event.choices and event.choices[1] then + local choice = event.choices[1] + if choice.delta and choice.delta.content then + output = output .. choice.delta.content + end + end + end, + callback = function() + callback(output) + -- __AUTO_GENERATED_PRINT_VAR_START__ + print([==[M.call#if#callback output:]==], vim.inspect(output)) -- __AUTO_GENERATED_PRINT_VAR_END__ + end, + }) + return + end + local api_token = get_api_token() local base_url = api_token.endpoints.proxy or api_token.endpoints.api diff --git a/lua/nes/context.lua b/lua/nes/context.lua index 2a40781..9561d4f 100644 --- a/lua/nes/context.lua +++ b/lua/nes/context.lua @@ -90,6 +90,31 @@ function Context.new(bufnr) return self end +---@class CurrentVersion +---@field text string + +---@class Context +---@field filename string +---@field original_code string +---@field edits string +---@field filetype string +---@field current_version CurrentVersion + +---@class Message +---@field role string +---@field content string + +---@class Payload +---@field messages Message[] +---@field model string +---@field temperature number +---@field top_p number +---@field prediction {type: string, content: string} +---@field n number +---@field stream boolean +---@field snippy {enabled: boolean} + +---@return Payload function Context:payload() -- copy from vscode return { diff --git a/lua/nes/core.lua b/lua/nes/core.lua index 3a9a07e..9dd40f8 100644 --- a/lua/nes/core.lua +++ b/lua/nes/core.lua @@ -279,6 +279,8 @@ function M.get_suggestion(bufnr) local ctx = Context.new(bufnr) local payload = ctx:payload() require("nes.api").call(payload, function(stdout) + -- __AUTO_GENERATED_PRINT_VAR_START__ + print([==[M.get_suggestion#(anon) stdout:]==], vim.inspect(stdout)) -- __AUTO_GENERATED_PRINT_VAR_END__ local next_version = vim.trim(stdout) assert(next_version) if not vim.startswith(next_version, "") then diff --git a/lua/nes/init.lua b/lua/nes/init.lua index 15610b9..6e813f9 100644 --- a/lua/nes/init.lua +++ b/lua/nes/init.lua @@ -1,7 +1,9 @@ local M = {} +M.opts = {} function M.setup(opts) opts = opts or {} + M.opts = opts vim.api.nvim_set_hl(0, "NesAdd", { link = "DiffAdd", default = true }) vim.api.nvim_set_hl(0, "NesDelete", { link = "DiffDelete", default = true }) diff --git a/samplecode.go b/samplecode.go new file mode 100644 index 0000000..d82bf8f --- /dev/null +++ b/samplecode.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + "fmt" + "math" + + "log/slog" +) + +var Args struct { + logLevel string +} + +func init() { + flag.StringVar(&Args.logLevel, "log-level", "info", "Set the log level") + flag.Parse() +} + +type Point struct { + x int + y int +} + +func NewPoint(x, y int) Point { + return Point{x: x, y: y} +} + +func (p *Point) Distance(other Point) float64 { + return math.Sqrt(float64((p.x-other.x)*(p.x-other.x) + (p.y-other.y)*(p.y-other.y))) +} + +func (p *Point) String() string { + return fmt.Sprintf("Point(%d, %d)", p.x, p.y) +} + +func main() { + slog.Info("Starting application", "logLevel", Args.logLevel) +}