diff options
| author | ThePrimeAgain <theprimeagain@theprimeagain.com> | 2025-11-26 09:21:53 -0700 |
|---|---|---|
| committer | ThePrimeAgain <theprimeagain@theprimeagain.com> | 2025-11-26 09:21:53 -0700 |
| commit | 82b05b232f6a8a2f26432a68759633783efb05ab (patch) | |
| tree | 3644a2dba6be9a2832880d076199d7553eac91dd /lua/99/request/init.lua | |
| parent | f901b32322e22f4cd2bf3c01896cbbcb37fecea8 (diff) | |
| download | a4-82b05b232f6a8a2f26432a68759633783efb05ab.tar.xz a4-82b05b232f6a8a2f26432a68759633783efb05ab.zip | |
fill in the function
Diffstat (limited to 'lua/99/request/init.lua')
| -rw-r--r-- | lua/99/request/init.lua | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/lua/99/request/init.lua b/lua/99/request/init.lua new file mode 100644 index 0000000..d020caa --- /dev/null +++ b/lua/99/request/init.lua @@ -0,0 +1,135 @@ +local Logger = require("99.logger.logger") +local editor = require("99.editor") +local geo = require("99.geo") +local Point = geo.Point + +--- TODO: some people change their current working directory as they open new +--- directories. if this is still the case in neovim land, then we will need +--- to make the _99_state have the project directory. +--- @return string +local function random_file() + return string.format("%s/tmp/99-%d", vim.uv.cwd(), math.floor(math.random() * 10000)) +end + +--- no, i am not going to use a uuid, in case of collision, call the police +--- @return string +local function get_id() + return tostring(math.floor(math.random() * 100000000)) +end + +--- @alias _99.Request.State "ready" | "calling-model" | "parsing-result" | "updating-file" + +--- @class _99.Request.Opts +--- @field model string +--- @field md_files string[] + +--- @class _99.Request +--- @field query string +--- @field tmp_name string +--- @field state _99.Request.State +--- @field buffer number +--- @field model string +--- @field id string +--- @field mark string +--- @field scopes Scope +--- @field system_prompt string +local Request = {} +Request.__index = Request + +--- @param opts _99.Request.Opts +function Request.new(opts) + assert(opts.model, "you must provide a model for hange requests to work") + + local ts = editor.treesitter + local cursor = Point:from_cursor() + local scopes = ts.function_scopes(cursor) + local buffer = vim.api.nvim_get_current_buf() + + return setmetatable({ + cursor = cursor, + scopes = scopes, + buffer = buffer, + model = opts.model, + tmp_name = random_file(), + id = get_id(), + state = "ready", + mark = "", + }, Request) +end + +function Request:has_scopes() + return self.scopes ~= nil and #self.scopes > 0 +end + +function Request:get_inner_scope() + assert(self:has_scopes(), "you cannot get inner scope if you dont have scopes") + return self.scopes.range[#self.scopes.range] +end + +--- @param prompt string +function Request:set_system_prompt(prompt) + self.system_prompt = prompt +end + +function Request:_retrieve_response() + local success, result = pcall(function() + return vim.fn.readfile(self.tmp_name) + end) + + if not success then + Logger:error("retrieve_results: failed to read file", "tmp_name", self.tmp_name, "error", result) + return false, "" + end + + return true, table.concat(result, "\n") +end + +--- @param res string +function Request:_update_file_with_changes(res) + local mark_pos = vim.api.nvim_buf_get_mark(self.buffer, self.mark) + local mark_point = Point:new(mark_pos[1], mark_pos[2] + 1) + + local ts = editor.treesitter + local scopes = ts.function_scopes(mark_point) + + if not scopes or not scopes:has_scope() then + Logger:error("update_file_with_changes: unable to find function at mark location") + return + end + + local range = scopes.range[#scopes.range] + + local function_start_row, _ = range.start:to_vim() + local function_end_row, _ = range.end_:to_vim() + + local lines = vim.split(res, "\n") + vim.api.nvim_buf_set_lines(self.buffer, function_start_row, function_end_row + 1, false, lines) +end + +function Request:start() + Logger:debug("99#make_query", "id", self.id, "query", self.query) + vim.system({ "opencode", "run", "-m", "anthropic/claude-sonnet-4-5", self.query }, { + text = true, + stdout = vim.schedule_wrap(function(err, data) + Logger:debug("STDOUT#data", "id", self.id, "data", data) + Logger:debug("STDOUT#error", "id", self.id, "err", err) + end), + stderr = vim.schedule_wrap(function(err, data) + Logger:debug("STDERR#data", "id", self.id, "data", data) + Logger:debug("STDERR#error", "id", self.id, "err", err) + end), + }, function(obj) + if obj.code ~= 0 then + Logger:fatal("opencode make_query failed", "request", self, "obj from results", obj) + return + end + vim.schedule(function() + local ok, res = self:_retrieve_response() + if ok then + self:_update_file_with_changes(res) + end + end) + end) +end + +return Request |
