summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/99/ops/make-prompt.lua18
-rw-r--r--lua/99/ops/over-range.lua23
-rw-r--r--lua/99/prompt-settings.lua29
-rw-r--r--lua/99/prompt.lua21
-rw-r--r--lua/99/providers.lua147
5 files changed, 109 insertions, 129 deletions
diff --git a/lua/99/ops/make-prompt.lua b/lua/99/ops/make-prompt.lua
index f60904b..cd19dcd 100644
--- a/lua/99/ops/make-prompt.lua
+++ b/lua/99/ops/make-prompt.lua
@@ -4,7 +4,7 @@ local Agents = require("99.extensions.agents")
--- @param context _99.Prompt
--- @param prompt string
--- @param opts _99.ops.Opts
---- @return string, _99.Reference[]
+--- @return string
return function(context, prompt, opts)
local user_prompt
@@ -19,20 +19,6 @@ return function(context, prompt, opts)
end
local full_prompt = prompt
- full_prompt = context._99.prompts.prompts.prompt(user_prompt, full_prompt)
- local refs = Completions.parse(user_prompt)
- local additional_rules = opts.additional_rules
- if additional_rules then
- for _, r in ipairs(additional_rules) do
- local content = Agents.get_rule_content(r)
- if content then
- table.insert(refs, {
- content = content,
- })
- end
- end
- end
-
- return full_prompt, refs
+ return full_prompt
end
diff --git a/lua/99/ops/over-range.lua b/lua/99/ops/over-range.lua
index 0562a7d..c1fca2a 100644
--- a/lua/99/ops/over-range.lua
+++ b/lua/99/ops/over-range.lua
@@ -3,6 +3,7 @@
local RequestStatus = require("99.ops.request_status")
local Mark = require("99.ops.marks")
+local BaseProvider = require("99.providers")
local geo = require("99.geo")
local make_prompt = require("99.ops.make-prompt")
local CleanUp = require("99.ops.clean-up")
@@ -48,10 +49,9 @@ local function over_range(context, opts)
end)
local system_cmd = context._99.prompts.prompts.visual_selection(range)
- local prompt, refs = make_prompt(context, system_cmd, opts)
+ local prompt = make_prompt(context, system_cmd, opts)
context:add_prompt_content(prompt)
- context:add_references(refs)
context:add_clean_up(clean_up)
top_status:start()
@@ -64,7 +64,7 @@ local function over_range(context, opts)
)
elseif status == "failed" then
logger:error(
- "request failed for visual_selection",
+ "request failed for visual selection",
"error response",
response or "no response provided"
)
@@ -78,16 +78,27 @@ local function over_range(context, opts)
return
end
- if vim.trim(response) == "" then
- print("response was empty, visual replacement aborted")
+ local dt =
+ BaseProvider.BareMetalProvider._parse_openai_response(
+ vim.json.decode(response)
+ ) --[[ @as _A4.OpenAIResponse ]]
+
+ dt.completion.message.content =
+ BaseProvider.BareMetalProvider._clean_response(
+ dt.completion.message.content
+ )
+
+ if vim.trim(dt.completion.message.content) == "" then
logger:debug(
"response was empty, visual replacement aborted"
)
return
end
+ context.req_response = dt.completion.message.content
+
local new_range = Range.from_marks(top_mark, bottom_mark)
- local lines = vim.split(response, "\n")
+ local lines = vim.split(dt.completion.message.content, "\n")
--- HACK: i am adding a new line here because above range will add a mark to the line above.
--- that way this appears to be added to "the same line" as the visual selection was
diff --git a/lua/99/prompt-settings.lua b/lua/99/prompt-settings.lua
index c221995..a311d68 100644
--- a/lua/99/prompt-settings.lua
+++ b/lua/99/prompt-settings.lua
@@ -115,36 +115,13 @@ Always use the temporary file as the place to describe your actions according to
</TaskDescription>
]]
end,
- --- @param prompt string
--- @param action string
- --- @param name? string defaults to DIRECTIONS
--- @return string
- prompt = function(prompt, action, name)
- name = name or "Prompt"
- return string.format(
- [[
-<Context>
-%s
-</Context>
-<%s>
-%s
-</%s>
-]],
- action,
- name,
- prompt,
- name
- )
+ prompt = function(action)
+ return string.format([[%s]], action)
end,
visual_selection = function(range)
- return string.format(
- [[
-<SELECTION_CONTENT>
-%s
-</SELECTION_CONTENT>
-]],
- range:to_text()
- )
+ return string.format([[%s]], range:to_text())
end,
}
diff --git a/lua/99/prompt.lua b/lua/99/prompt.lua
index 6623987..347db0d 100644
--- a/lua/99/prompt.lua
+++ b/lua/99/prompt.lua
@@ -300,8 +300,6 @@ function Prompt:start_request(observer)
local ok = self:finalize()
l:assert(ok, "context failed to finalize")
- --- TODO: create a prompt context class that can actually organize.
- --- do not do this during the request context refactoring, but next
local prompt = table.concat(self.agent_context, "\n")
local obs = self:_observer(observer)
local provider = self._99.provider_override
@@ -499,18 +497,13 @@ function Prompt:finalize()
end
self:_read_md_files()
- local ok, visual_data = pcall(self.visual_data, self)
- if ok then
- local f_loc = self._99.prompts.get_file_location(
- self.full_path,
- visual_data.range
- )
- table.insert(self.agent_context, f_loc)
- table.insert(
- self.agent_context,
- self._99.prompts.get_range_text(visual_data.range)
- )
- end
+ --local ok, visual_data = pcall(self.visual_data, self)
+ --if ok then
+ -- table.insert(
+ -- self.agent_context,
+ -- self._99.prompts.get_range_text(visual_data.range)
+ -- )
+ --end
return true, self
end
diff --git a/lua/99/providers.lua b/lua/99/providers.lua
index 8875ca8..63e64aa 100644
--- a/lua/99/providers.lua
+++ b/lua/99/providers.lua
@@ -1,7 +1,7 @@
--- @class _99.Providers.Observer
--- @field on_stdout fun(line: string): nil
--- @field on_stderr fun(line: string): nil
---- @field on_complete fun(status: _99.Prompt.EndingState, res: string): nil
+--- @field on_complete fun(status: _99.Prompt.EndingState, res: string|table): nil
--- @field on_start fun(): nil
--- @param fn fun(...: any): nil
@@ -62,54 +62,6 @@ end
--- @field predictedPerTkMs number
--- @field predictedPerSec number
---- @param raw table
---- @return _A4.OpenAIResponse
-local function parse_openai_response(raw)
- local choice = raw.choices[1]
-
- --- @type _A4.OpenAIResponse
- local response = {
- completion = {
- finishReason = choice.finish_reason,
- index = choice.index,
- message = {
- role = choice.message.role,
- content = choice.message.content,
- },
- },
- metadata = {
- created = raw.created,
- model = raw.model,
- systemFingerPrint = raw.system_fingerprint,
- object = raw.object,
- usage = {
- completionTks = raw.usage.completion_tokens,
- promptTks = raw.usage.prompt_tokens,
- totalTks = raw.usage.total_tokens,
- promptTksDetails = {
- cachedTks = raw.usage.prompt_tokens_details.cached_tokens,
- },
- },
- },
- id = {
- id = raw.id,
- },
- timings = {
- cacheN = raw.timings.cache_n,
- promptN = raw.timings.prompt_n,
- promptMs = raw.timings.prompt_ms,
- promptPerTkMs = raw.timings.prompt_per_token_ms,
- promptPerSec = raw.timings.prompt_per_second,
- predictedN = raw.timings.predicted_n,
- predictedMs = raw.timings.predicted_ms,
- predictedPerTkMs = raw.timings.predicted_per_token_ms,
- predictedPerSec = raw.timings.predicted_per_second,
- },
- }
-
- return response
-end
-
--- @class _99.Providers.BaseProvider
--- @field _build_command fun(self: _99.Providers.BaseProvider, query: string, context: _99.Prompt): string[]
--- @field _get_provider_name fun(self: _99.Providers.BaseProvider): string
@@ -123,8 +75,8 @@ end
--- @param data string
--- @return string
-function BaseProvider:_clean_response(data)
- local _data, _ = data:gsub("```[a-z]*\n", ""):gsub(" ```", "")
+function BaseProvider._clean_response(data)
+ local _data, _ = data:gsub("```[a-z]*\n", ""):gsub("```", "")
return _data
end
@@ -164,9 +116,6 @@ function BaseProvider:_retrieve_response(context)
end
end
--- TODO: Remember that we are ditching the tmp_file; likely 90%
--- You can just grab the json data and dump it in logs honestly
--- files only make sense for agentic flows
--- @param query string
--- @param context _99.Prompt
--- @param observer _99.Providers.Observer
@@ -192,21 +141,25 @@ function BaseProvider:make_request(query, context, observer)
command,
{ text = true },
vim.schedule_wrap(function(obj)
- if obj.code ~= 0 then
- once_complete("failed", obj.stderr)
+ logger:debug("exit callback fired", "code", tostring(obj.code))
+ logger:debug("schedule_wrap", "stdout", tostring(obj.stdout))
+ logger:debug("schedule_wrap", "stderr", tostring(obj.stderr))
+
+ if context:is_cancelled() then
+ once_complete("cancelled", "")
return
end
- local data = parse_openai_response(vim.json.decode(obj.stdout))
- if self._get_provider_name == "BareMetalProvider" then
- data.completion.message.content =
- self:_clean_response(data.completion.message.content)
- context.req_response = data.completion.message.content
+ if obj.code ~= 0 then
+ once_complete("failed", obj.stderr or "")
+ return
end
- once_complete("success", data.completion.message.content)
+
+ once_complete("success", obj.stdout)
end)
)
+ logger:debug("proc spawned", "proc_id", tostring(proc))
context:_set_process(proc)
end
@@ -400,7 +353,8 @@ function GeminiCLIProvider._get_default_model()
end
--- @class BareMetalProvider : _99.Providers.BaseProvider
---- @field _clean_response fun(self: _99.Providers.BaseProvider, data : string): string
+--- @field _clean_response fun(data : string): string
+--- @field _parse_openai_response fun(raw: table): _A4.OpenAIResponse
local BareMetalProvider = setmetatable({}, { __index = BaseProvider })
--- @param query string
@@ -412,11 +366,22 @@ function BareMetalProvider._build_command(_, query, context)
"-s",
context.endpoint,
"-H",
- '"Content-Type: applications/json"',
+ "Content-Type: application/json",
"-d",
- '"{"messages":[{"role":"system","content":"You are a strict code completion backend for Neovim. Your input will be a code snippet, function signature, or a comment requesting code. CRITICAL DIRECTIONS: 1. Output ONLY valid, executable programming code. 2. Do NOT wrap your response in markdown code blocks. 3. Do NOT include any conversational filler, explanations, greetings, or sign-offs. 4. If you cannot fulfill the request, output nothing or a code comment explaining why."},{"role":"user","content":"'
- .. query
- .. '"}],"temperature":0.0,"stream":false}"',
+ vim.json.encode({
+ messages = {
+ {
+ role = "system",
+ content = "You are a strict code completion backend for Neovim. Your input will be a code snippet, function signature, or a comment requesting code. CRITICAL DIRECTIONS: 1. Output ONLY valid, executable programming code. 2. Do NOT wrap your response in markdown code blocks. 3. Do NOT include any conversational filler, explanations, greetings, or sign-offs. 4. If you cannot fulfill the request, output nothing or a code comment explaining why.",
+ },
+ {
+ role = "user",
+ content = query,
+ },
+ },
+ temperature = 0.0,
+ stream = false,
+ }),
}
end
@@ -436,6 +401,54 @@ function BareMetalProvider.fetch_models(callback)
}, nil)
end
+--- @param raw table
+--- @return _A4.OpenAIResponse
+function BareMetalProvider._parse_openai_response(raw)
+ local choice = raw.choices[1]
+
+ --- @type _A4.OpenAIResponse
+ local response = {
+ completion = {
+ finishReason = choice.finish_reason,
+ index = choice.index,
+ message = {
+ role = choice.message.role,
+ content = choice.message.content,
+ },
+ },
+ metadata = {
+ created = raw.created,
+ model = raw.model,
+ systemFingerPrint = raw.system_fingerprint,
+ object = raw.object,
+ usage = {
+ completionTks = raw.usage.completion_tokens,
+ promptTks = raw.usage.prompt_tokens,
+ totalTks = raw.usage.total_tokens,
+ promptTksDetails = {
+ cachedTks = raw.usage.prompt_tokens_details.cached_tokens,
+ },
+ },
+ },
+ id = {
+ id = raw.id,
+ },
+ timings = {
+ cacheN = raw.timings.cache_n,
+ promptN = raw.timings.prompt_n,
+ promptMs = raw.timings.prompt_ms,
+ promptPerTkMs = raw.timings.prompt_per_token_ms,
+ promptPerSec = raw.timings.prompt_per_second,
+ predictedN = raw.timings.predicted_n,
+ predictedMs = raw.timings.predicted_ms,
+ predictedPerTkMs = raw.timings.predicted_per_token_ms,
+ predictedPerSec = raw.timings.predicted_per_second,
+ },
+ }
+
+ return response
+end
+
return {
BaseProvider = BaseProvider,
OpenCodeProvider = OpenCodeProvider,