refactor: planning mode user prompt use aider prompt (#671)
This commit is contained in:
@@ -23,7 +23,9 @@ M.defaults = {
|
||||
-- You can use `require('avante.config').override({system_prompt = "MY_SYSTEM_PROMPT"}) conditionally
|
||||
-- in your own autocmds to do it per directory, or that fit your needs.
|
||||
system_prompt = [[
|
||||
You are an excellent programming expert.
|
||||
Act as an expert software developer.
|
||||
Always use best practices when coding.
|
||||
Respect and use existing conventions, libraries, etc that are already present in the code base.
|
||||
]],
|
||||
---@type AvanteSupportedProvider
|
||||
openai = {
|
||||
|
||||
@@ -362,7 +362,13 @@ function Selection:create_editing_input()
|
||||
---@type AvanteChunkParser
|
||||
local on_chunk = function(chunk)
|
||||
full_response = full_response .. chunk
|
||||
local response_lines = vim.split(full_response, "\n")
|
||||
local response_lines_ = vim.split(full_response, "\n")
|
||||
local response_lines = {}
|
||||
for i, line in ipairs(response_lines_) do
|
||||
if not (string.match(line, "^```") and (i == 1 or i == #response_lines_)) then
|
||||
table.insert(response_lines, line)
|
||||
end
|
||||
end
|
||||
if #response_lines == 1 then
|
||||
local first_line = response_lines[1]
|
||||
local first_line_indentation = Utils.get_indentation(first_line)
|
||||
|
||||
@@ -133,51 +133,6 @@ function Sidebar:toggle(opts)
|
||||
end
|
||||
end
|
||||
|
||||
local function realign_line_numbers(code_lines, snippet)
|
||||
local snippet_lines = vim.split(snippet.content, "\n")
|
||||
local snippet_lines_count = #snippet_lines
|
||||
|
||||
local start_line = snippet.range[1]
|
||||
|
||||
local correct_start
|
||||
for i = start_line, math.max(1, start_line - snippet_lines_count + 1), -1 do
|
||||
local matched = true
|
||||
for j = 1, math.min(snippet_lines_count, start_line - i + 1) do
|
||||
if code_lines[i + j - 1] ~= snippet_lines[j] then
|
||||
matched = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if matched then
|
||||
correct_start = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local end_line = snippet.range[2]
|
||||
|
||||
local correct_end
|
||||
for i = snippet_lines_count - 1, 1, -1 do
|
||||
local matched = true
|
||||
for j = 1, i do
|
||||
if code_lines[end_line + j - 1] ~= snippet_lines[snippet_lines_count - j] then
|
||||
matched = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if matched then
|
||||
correct_end = end_line + i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if correct_start then snippet.range[1] = correct_start end
|
||||
|
||||
if correct_end then snippet.range[2] = correct_end end
|
||||
|
||||
return snippet
|
||||
end
|
||||
|
||||
---@class AvanteReplacementResult
|
||||
---@field content string
|
||||
---@field is_searching boolean
|
||||
@@ -317,11 +272,9 @@ end
|
||||
---@field start_line_in_response_buf integer
|
||||
---@field end_line_in_response_buf integer
|
||||
|
||||
---@param code_content string
|
||||
---@param response_content string
|
||||
---@return AvanteCodeSnippet[]
|
||||
local function extract_code_snippets(code_content, response_content)
|
||||
local code_lines = vim.split(code_content, "\n")
|
||||
local function extract_code_snippets(response_content)
|
||||
local snippets = {}
|
||||
local current_snippet = {}
|
||||
local in_code_block = false
|
||||
@@ -358,7 +311,6 @@ local function extract_code_snippets(code_content, response_content)
|
||||
start_line_in_response_buf = start_line_in_response_buf,
|
||||
end_line_in_response_buf = idx,
|
||||
}
|
||||
snippet = realign_line_numbers(code_lines, snippet)
|
||||
table.insert(snippets, snippet)
|
||||
end
|
||||
current_snippet = {}
|
||||
@@ -448,7 +400,6 @@ local function insert_conflict_contents(bufnr, snippets)
|
||||
local snippet_lines = vim.split(snippet.content, "\n")
|
||||
|
||||
for idx, line in ipairs(snippet_lines) do
|
||||
line = Utils.trim_line_number(line)
|
||||
if idx == 1 then
|
||||
local indentation = Utils.get_indentation(line)
|
||||
need_prepend_indentation = indentation ~= original_start_line_indentation
|
||||
@@ -512,7 +463,7 @@ end
|
||||
function Sidebar:apply(current_cursor)
|
||||
local content = table.concat(Utils.get_buf_lines(0, -1, self.code.bufnr), "\n")
|
||||
local response, response_start_line = self:get_content_between_separators()
|
||||
local all_snippets = extract_code_snippets(content, response)
|
||||
local all_snippets = extract_code_snippets(response)
|
||||
all_snippets = ensure_snippets_no_overlap(content, all_snippets)
|
||||
local selected_snippets = {}
|
||||
if current_cursor then
|
||||
@@ -951,7 +902,7 @@ function Sidebar:is_focused_on(winid)
|
||||
end
|
||||
|
||||
---@param content string concatenated content of the buffer
|
||||
---@param opts? {focus?: boolean, stream?: boolean, scroll?: boolean, callback?: fun(): nil} whether to focus the result view
|
||||
---@param opts? {focus?: boolean, stream?: boolean, scroll?: boolean, backspace?: integer, callback?: fun(): nil} whether to focus the result view
|
||||
function Sidebar:update_content(content, opts)
|
||||
if not self.result or not self.result.bufnr then return end
|
||||
opts = vim.tbl_deep_extend("force", { focus = true, scroll = true, stream = false, callback = nil }, opts or {})
|
||||
@@ -974,8 +925,18 @@ function Sidebar:update_content(content, opts)
|
||||
vim.schedule(function()
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then return end
|
||||
scroll_to_bottom()
|
||||
local lines = vim.split(content, "\n")
|
||||
Utils.unlock_buf(self.result.bufnr)
|
||||
if opts.backspace ~= nil then
|
||||
-- Delete the specified number of char from the end of the buffer
|
||||
-- sends the buffer to the backend
|
||||
for _ = 1, opts.backspace do
|
||||
api.nvim_buf_call(
|
||||
self.result.bufnr,
|
||||
function() api.nvim_feedkeys(api.nvim_replace_termcodes("<BS>", true, false, true), "n", true) end
|
||||
)
|
||||
end
|
||||
end
|
||||
local lines = vim.split(content, "\n")
|
||||
api.nvim_buf_call(self.result.bufnr, function() api.nvim_put(lines, "c", true, true) end)
|
||||
Utils.lock_buf(self.result.bufnr)
|
||||
api.nvim_set_option_value("filetype", "Avante", { buf = self.result.bufnr })
|
||||
@@ -1197,15 +1158,11 @@ function Sidebar:create_input(opts)
|
||||
self:update_content(content_prefix .. "**Generating response ...**\n")
|
||||
|
||||
local content = table.concat(Utils.get_buf_lines(0, -1, self.code.bufnr), "\n")
|
||||
local content_with_line_numbers = Utils.prepend_line_number(content)
|
||||
|
||||
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr })
|
||||
|
||||
local selected_code_content_with_line_numbers = nil
|
||||
if self.code.selection ~= nil then
|
||||
selected_code_content_with_line_numbers =
|
||||
Utils.prepend_line_number(self.code.selection.content, self.code.selection.range.start.line)
|
||||
end
|
||||
local selected_code_content = nil
|
||||
if self.code.selection ~= nil then selected_code_content = self.code.selection.content end
|
||||
|
||||
if request:sub(1, 1) == "/" then
|
||||
local command, args = request:match("^/(%S+)%s*(.*)")
|
||||
@@ -1228,10 +1185,8 @@ function Sidebar:create_input(opts)
|
||||
Utils.error("Invalid end line number", { once = true, title = "Avante" })
|
||||
return
|
||||
end
|
||||
selected_code_content_with_line_numbers = Utils.prepend_line_number(
|
||||
table.concat(api.nvim_buf_get_lines(self.code.bufnr, start_line - 1, end_line, false), "\n"),
|
||||
start_line
|
||||
)
|
||||
selected_code_content =
|
||||
table.concat(api.nvim_buf_get_lines(self.code.bufnr, start_line - 1, end_line, false), "\n")
|
||||
request = question
|
||||
end)
|
||||
else
|
||||
@@ -1244,20 +1199,36 @@ function Sidebar:create_input(opts)
|
||||
end
|
||||
end
|
||||
|
||||
local full_response = ""
|
||||
local original_response = ""
|
||||
local transformed_response = ""
|
||||
local displayed_response = ""
|
||||
|
||||
local is_first_chunk = true
|
||||
|
||||
local prev_is_searching = false
|
||||
|
||||
---@type AvanteChunkParser
|
||||
local on_chunk = function(chunk)
|
||||
full_response = full_response .. chunk
|
||||
original_response = original_response .. chunk
|
||||
local transformed = transform_result_content(content, transformed_response .. chunk, filetype)
|
||||
transformed_response = transformed.content
|
||||
prev_is_searching = transformed.is_searching
|
||||
local cur_displayed_response = generate_display_content(transformed)
|
||||
if is_first_chunk then
|
||||
is_first_chunk = false
|
||||
self:update_content(content_prefix .. chunk, { stream = false, scroll = true })
|
||||
return
|
||||
end
|
||||
self:update_content(chunk, { stream = true, scroll = true })
|
||||
vim.schedule(function() vim.cmd("redraw") end)
|
||||
if cur_displayed_response ~= displayed_response then
|
||||
local backspace = nil
|
||||
if prev_is_searching and not transformed.is_searching then backspace = #searching_hints[1] end
|
||||
displayed_response = cur_displayed_response
|
||||
self:update_content(
|
||||
content_prefix .. displayed_response,
|
||||
{ stream = false, scroll = true, backspace = backspace }
|
||||
)
|
||||
vim.schedule(function() vim.cmd("redraw") end)
|
||||
end
|
||||
end
|
||||
|
||||
---@type AvanteCompleteParser
|
||||
@@ -1286,7 +1257,8 @@ function Sidebar:create_input(opts)
|
||||
provider = Config.provider,
|
||||
model = model,
|
||||
request = request,
|
||||
response = full_response,
|
||||
response = displayed_response,
|
||||
original_response = original_response,
|
||||
})
|
||||
Path.history.save(self.code.bufnr, chat_history)
|
||||
end
|
||||
@@ -1302,9 +1274,9 @@ function Sidebar:create_input(opts)
|
||||
bufnr = self.code.bufnr,
|
||||
ask = opts.ask,
|
||||
project_context = vim.json.encode(project_context),
|
||||
file_content = content_with_line_numbers,
|
||||
file_content = content,
|
||||
code_lang = filetype,
|
||||
selected_code = selected_code_content_with_line_numbers,
|
||||
selected_code = selected_code_content,
|
||||
instructions = request,
|
||||
mode = "planning",
|
||||
on_chunk = on_chunk,
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
{% block user_prompt %}
|
||||
Your task is to modify the provided code according to the user's request. Follow these instructions precisely:
|
||||
|
||||
1. Return ONLY the complete modified code.
|
||||
1. Return *ONLY* the complete modified code.
|
||||
|
||||
2. Do not include any explanations, comments, or line numbers in your response.
|
||||
2. *DO NOT* include three backticks: {%raw%}```{%endraw%} in your suggestion! Treat the suggested code AS IS.
|
||||
|
||||
3. Ensure the returned code is complete and can be directly used as a replacement for the original code.
|
||||
3. *DO NOT* include any explanations, comments, or line numbers in your response.
|
||||
|
||||
4. Preserve the original structure, indentation, and formatting of the code as much as possible.
|
||||
4. Ensure the returned code is complete and can be directly used as a replacement for the original code.
|
||||
|
||||
5. Do not omit any parts of the code, even if they are unchanged.
|
||||
5. Preserve the original structure, indentation, and formatting of the code as much as possible.
|
||||
|
||||
6. Maintain the SAME indentation in the returned code as in the source code
|
||||
6. *DO NOT* omit any parts of the code, even if they are unchanged.
|
||||
|
||||
7. DO NOT include three backticks: {%raw%}```{%endraw%} in your suggestion. Treat the suggested code AS IS.
|
||||
7. Maintain the *SAME INDENTATION* in the returned code as in the source code
|
||||
|
||||
8. Only return the new code snippets to be updated, DO NOT return the entire file content.
|
||||
8. *ONLY* return the new code snippets to be updated, *DO NOT* return the entire file content.
|
||||
|
||||
Remember that Your response SHOULD CONTAIN ONLY THE MODIFIED CODE to be used as DIRECT REPLACEMENT to the original file.
|
||||
{% endblock %}
|
||||
|
||||
@@ -12,49 +12,138 @@
|
||||
INSTRUCTION:{% else -%}
|
||||
<instruction>{% endif -%}
|
||||
{% block user_prompt %}
|
||||
Your primary task is to suggest code modifications with precise line number ranges. Follow these instructions meticulously:
|
||||
Take requests for changes to the supplied code.
|
||||
If the request is ambiguous, ask questions.
|
||||
|
||||
1. Carefully analyze the original code, paying close attention to its structure and line numbers. Line numbers start from 1 and include ALL lines, even empty ones.
|
||||
Always reply to the user in the same language they are using.
|
||||
|
||||
2. When suggesting modifications:
|
||||
a. Use the language in the question to reply. If there are non-English parts in the question, use the language of those parts.
|
||||
b. Explain why the change is necessary or beneficial.
|
||||
c. If an image is provided, make sure to use the image in conjunction with the code snippet.
|
||||
d. Provide the exact code snippet to be replaced using this format:
|
||||
{% raw %}
|
||||
Replace lines: {{start_line}}-{{end_line}}
|
||||
```{{language}}
|
||||
{{suggested_code}}
|
||||
```
|
||||
{% endraw %}
|
||||
3. Crucial guidelines for suggested code snippets:
|
||||
- The content regarding line numbers MUST strictly follow the format "Replace lines: {%raw%}{{start_line}}{%endraw%}-{%raw%}{{end_line}}{%endraw%}". Do not be lazy!
|
||||
- Only apply the change(s) suggested by the most recent assistant message (before your generation).
|
||||
- Do not make any unrelated changes to the code.
|
||||
- Produce a valid full rewrite of the entire original file without skipping any lines. Do not be lazy!
|
||||
- Do not arbitrarily delete pre-existing comments/empty Lines.
|
||||
- Do not omit large parts of the original file for no reason.
|
||||
- Do not omit any needed changes from the requisite messages/code blocks.
|
||||
- If there is a clicked code block, bias towards just applying that (and applying other changes implied).
|
||||
- Please keep your suggested code changes minimal, and do not include irrelevant lines in the code snippet.
|
||||
- Maintain the SAME indentation in the returned code as in the source code
|
||||
Once you understand the request you MUST:
|
||||
|
||||
4. Crucial guidelines for line numbers:
|
||||
- The range {%raw%}{{start_line}}{%endraw%}-{%raw%}{{end_line}}{%endraw%} is INCLUSIVE. Both start_line and end_line are included in the replacement.
|
||||
- Count EVERY line, including empty lines and comments lines, comments. Do not be lazy!
|
||||
- Use the same number for start and end lines for single-line changes.
|
||||
- For multi-line changes, ensure the range covers ALL affected lines, from first to last.
|
||||
- Double-check that your line numbers align perfectly with the original code structure.
|
||||
1. Decide if you need to propose *SEARCH/REPLACE* edits to any files that haven't been added to the chat. You can create new files without asking!
|
||||
|
||||
5. Final check:
|
||||
- Review all suggestions, ensuring each line number is correct, especially the start_line and end_line.
|
||||
- Confirm that no unrelated code is accidentally modified or deleted.
|
||||
- Verify that the start_line and end_line correctly include all intended lines for replacement.
|
||||
- Perform a final alignment check to ensure your line numbers haven't shifted, especially the start_line.
|
||||
- Double-check that your line numbers align perfectly with the original code structure.
|
||||
- DO NOT return the complete modified code with applied changes!
|
||||
But if you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*.
|
||||
End your reply and wait for their approval.
|
||||
You can keep asking if you then decide you need to edit more files.
|
||||
|
||||
Remember that ACCURATE line numbers are CRITICAL. The range {%raw%}{{start_line}}{%endraw%} to {%raw%}{{end_line}}{%endraw%} must include ALL LINES to be replaced. Double-check ALL RANGES before finalizing your response, and MAKE SURE THAT {%raw%}{{start_line}}{%endraw%} hasn't been shifted down. ENSURE line numbers MATCH the original code structure and indentation ARE PRESERVED.
|
||||
2. Think step-by-step and explain the needed changes in a few short sentences.
|
||||
|
||||
3. Describe each change with a *SEARCH/REPLACE block* per the examples below.
|
||||
|
||||
All changes to files must use this *SEARCH/REPLACE block* format.
|
||||
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
|
||||
|
||||
# Example conversations:
|
||||
|
||||
## USER: Change get_factorial() to use math.factorial
|
||||
|
||||
## ASSISTANT: To make this change we need to modify `mathweb/flask/app.py` to:
|
||||
|
||||
1. Import the math package.
|
||||
2. Remove the existing factorial() function.
|
||||
3. Update get_factorial() to call math.factorial instead.
|
||||
|
||||
Here are the *SEARCH/REPLACE* blocks:
|
||||
|
||||
mathweb/flask/app.py
|
||||
<SEARCH>
|
||||
from flask import Flask
|
||||
</SEARCH>
|
||||
<REPLACE>
|
||||
import math
|
||||
from flask import Flask
|
||||
<REPLACE>
|
||||
|
||||
mathweb/flask/app.py
|
||||
<SEARCH>
|
||||
def factorial(n):
|
||||
"compute factorial"
|
||||
|
||||
if n == 0:
|
||||
return 1
|
||||
else:
|
||||
return n * factorial(n-1)
|
||||
|
||||
</SEARCH>
|
||||
<REPLACE>
|
||||
</REPLACE>
|
||||
|
||||
mathweb/flask/app.py
|
||||
<SEARCH>
|
||||
return str(factorial(n))
|
||||
</SEARCH>
|
||||
<REPLACE>
|
||||
return str(math.factorial(n))
|
||||
</REPLACE>
|
||||
|
||||
|
||||
## USER: Refactor hello() into its own file.
|
||||
|
||||
## ASSISTANT: To make this change we need to modify `main.py` and make a new file `hello.py`:
|
||||
|
||||
1. Make a new hello.py file with hello() in it.
|
||||
2. Remove hello() from main.py and replace it with an import.
|
||||
|
||||
Here are the *SEARCH/REPLACE* blocks:
|
||||
|
||||
hello.py
|
||||
<SEARCH>
|
||||
</SEARCH>
|
||||
<REPLACE>
|
||||
def hello():
|
||||
"print a greeting"
|
||||
|
||||
print("hello")
|
||||
</REPLACE>
|
||||
|
||||
main.py
|
||||
<SEARCH>
|
||||
def hello():
|
||||
"print a greeting"
|
||||
|
||||
print("hello")
|
||||
</SEARCH>
|
||||
<REPLACE>
|
||||
from hello import hello
|
||||
</REPLACE>
|
||||
# *SEARCH/REPLACE block* Rules:
|
||||
|
||||
Every *SEARCH/REPLACE block* must use this format:
|
||||
1. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc.
|
||||
2. The start of search block: <SEARCH>
|
||||
3. A contiguous chunk of lines to search for in the existing source code
|
||||
4. The end of the search block: </SEARCH>
|
||||
5. The start of replace block: <REPLACE>
|
||||
6. The lines to replace into the source code
|
||||
7. The end of the replace block: </REPLACE>
|
||||
|
||||
Use the *FULL* file path, as shown to you by the user.
|
||||
|
||||
Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
|
||||
If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup.
|
||||
|
||||
*SEARCH/REPLACE* blocks will replace *all* matching occurrences.
|
||||
Include enough lines to make the SEARCH blocks uniquely match the lines to change.
|
||||
|
||||
Keep *SEARCH/REPLACE* blocks concise.
|
||||
Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file.
|
||||
Include just the changing lines, and a few surrounding lines if needed for uniqueness.
|
||||
Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks.
|
||||
|
||||
Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat!
|
||||
|
||||
To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location.
|
||||
|
||||
Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file.
|
||||
|
||||
If you want to put code in a new file, use a *SEARCH/REPLACE block* with:
|
||||
- A new file path, including dir name if needed
|
||||
- An empty `SEARCH` section
|
||||
- The new file's contents in the `REPLACE` section
|
||||
|
||||
To rename files which have been added to the chat, use shell commands at the end of your response.
|
||||
|
||||
|
||||
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
|
||||
{% endblock %}
|
||||
{%- if use_xml_format -%}
|
||||
</instruction>
|
||||
|
||||
Reference in New Issue
Block a user