-
Notifications
You must be signed in to change notification settings - Fork 8
Open Router support #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
Comment on lines
+95
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current stream processing logic may not be robust enough to handle cases where multiple Server-Sent Events (SSE) arrive in a single data chunk. The implementation assumes one I recommend iterating over each line in the chunk to process each event separately. This will make the streaming logic more resilient. |
||
| callback = function() | ||
| callback(output) | ||
| -- __AUTO_GENERATED_PRINT_VAR_START__ | ||
| print([==[M.call#if#callback output:]==], vim.inspect(output)) -- __AUTO_GENERATED_PRINT_VAR_END__ | ||
|
Comment on lines
+118
to
+119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| end, | ||
| }) | ||
| return | ||
| end | ||
|
|
||
| local api_token = get_api_token() | ||
| local base_url = api_token.endpoints.proxy or api_token.endpoints.api | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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__ | ||
|
Comment on lines
+282
to
+283
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| local next_version = vim.trim(stdout) | ||
| assert(next_version) | ||
| if not vim.startswith(next_version, "<next-version>") then | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation for
base_urlis inconsistent with the implementation. The example value and the default mentioned in the comment (https://api.openrouter.ai/v1) point to a base path, but the code expects the full endpoint URL for chat completions. The actual default in the code ishttps://openrouter.ai/api/v1/chat/completions.This discrepancy will likely confuse users and lead to incorrect configurations. Please update the documentation to reflect the correct default value and clarify that the full endpoint URL is expected.