add possibility to define a project based instruction file
This commit is contained in:
23
README.md
23
README.md
@@ -61,6 +61,7 @@ If you like this project, please consider supporting me on Patreon, as it helps
|
||||
|
||||
- **AI-Powered Code Assistance**: Interact with AI to ask questions about your current code file and receive intelligent suggestions for improvement or modification.
|
||||
- **One-Click Application**: Quickly apply the AI's suggested changes to your source code with a single command, streamlining the editing process and saving time.
|
||||
- **Project-Specific Instruction Files**: Customize AI behavior by adding a markdown file (`avante.md` by default) in the project root. This file is automatically referenced during workspace changes. You can also configure a custom file name for tailored project instructions.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -84,6 +85,8 @@ For building binary if you wish to build from source, then `cargo` is required.
|
||||
---@type avante.Config
|
||||
opts = {
|
||||
-- add any opts here
|
||||
-- this file can containe specific instructions for your project
|
||||
instructions_file = "avante.md"
|
||||
-- for example
|
||||
provider = "claude",
|
||||
providers = {
|
||||
@@ -656,6 +659,7 @@ For other users just add a custom provider
|
||||
Avante.nvim provides several completion sources that can be integrated with blink.cmp:
|
||||
|
||||
#### Mentions (`@` trigger)
|
||||
|
||||
Mentions allow you to quickly reference specific features or add files to the chat context:
|
||||
|
||||
- `@codebase` - Enable project context and repository mapping
|
||||
@@ -665,6 +669,7 @@ Mentions allow you to quickly reference specific features or add files to the ch
|
||||
- `@buffers` - Add open buffers to chat context
|
||||
|
||||
#### Slash Commands (`/` trigger)
|
||||
|
||||
Built-in slash commands for common operations:
|
||||
|
||||
- `/help` - Show help message with available commands
|
||||
@@ -676,6 +681,7 @@ Built-in slash commands for common operations:
|
||||
- `/commit` - Generate commit message for changes
|
||||
|
||||
#### Shortcuts (`#` trigger)
|
||||
|
||||
Shortcuts provide quick access to predefined prompt templates. You can customize these in your config:
|
||||
|
||||
```lua
|
||||
@@ -983,6 +989,7 @@ Fast Apply is a feature that enables instant code edits with high accuracy by le
|
||||
Fast Apply addresses the common pain point of slow code application in AI-assisted development. Instead of waiting for a full language model to process and apply changes, Fast Apply uses a specialized "apply model" that can quickly and accurately merge code edits with 96-98% accuracy at speeds of 2500-4500+ tokens per second.
|
||||
|
||||
Key benefits:
|
||||
|
||||
- **Instant application**: Code changes are applied immediately without noticeable delays
|
||||
- **High accuracy**: Specialized models achieve 96-98% accuracy for code edits
|
||||
- **Seamless workflow**: Maintains the natural flow of development without interruptions
|
||||
@@ -993,6 +1000,7 @@ Key benefits:
|
||||
To enable Fast Apply, you need to:
|
||||
|
||||
1. **Enable Fast Apply in your configuration**:
|
||||
|
||||
```lua
|
||||
behaviour = {
|
||||
enable_fastapply = true, -- Enable Fast Apply feature
|
||||
@@ -1004,6 +1012,7 @@ To enable Fast Apply, you need to:
|
||||
Go to [morphllm.com](https://morphllm.com/api-keys) and create an account and get the API key.
|
||||
|
||||
3. **Set your Morph API key**:
|
||||
|
||||
```bash
|
||||
export MORPH_API_KEY="your-api-key"
|
||||
```
|
||||
@@ -1021,11 +1030,11 @@ To enable Fast Apply, you need to:
|
||||
|
||||
Morph provides different models optimized for different use cases:
|
||||
|
||||
| Model | Speed | Accuracy | Context Limit |
|
||||
|-------|-------|----------|---------------|
|
||||
| `morph-v3-fast` | 4500+ tok/sec | 96% | 16k tokens |
|
||||
| `morph-v3-large` | 2500+ tok/sec | 98% | 16k tokens |
|
||||
| `auto` | 2500-4500 tok/sec | 98% | 16k tokens |
|
||||
| Model | Speed | Accuracy | Context Limit |
|
||||
| ---------------- | ----------------- | -------- | ------------- |
|
||||
| `morph-v3-fast` | 4500+ tok/sec | 96% | 16k tokens |
|
||||
| `morph-v3-large` | 2500+ tok/sec | 98% | 16k tokens |
|
||||
| `auto` | 2500-4500 tok/sec | 98% | 16k tokens |
|
||||
|
||||
### How It Works
|
||||
|
||||
@@ -1037,6 +1046,7 @@ When Fast Apply is enabled and a Morph provider is configured, avante.nvim will:
|
||||
4. Apply the changes directly to your files with high accuracy
|
||||
|
||||
The process uses a specialized prompt format that includes:
|
||||
|
||||
- `<instructions>`: Clear description of what changes to make
|
||||
- `<code>`: The original code content
|
||||
- `<update>`: The specific changes using truncation markers (`// ... existing code ...`)
|
||||
@@ -1387,6 +1397,7 @@ Avante.nvim can be extended to work with other plugins by using its extension mo
|
||||
### How to disable agentic mode?
|
||||
|
||||
Avante.nvim provides two interaction modes:
|
||||
|
||||
- **`agentic`** (default): Uses AI tools to automatically generate and apply code changes
|
||||
- **`legacy`**: Uses the traditional planning method without automatic tool execution
|
||||
|
||||
@@ -1400,10 +1411,12 @@ To disable agentic mode and switch to legacy mode, update your configuration:
|
||||
```
|
||||
|
||||
**What's the difference?**
|
||||
|
||||
- **Agentic mode**: AI can automatically execute tools like file operations, bash commands, web searches, etc. to complete complex tasks
|
||||
- **Legacy mode**: AI provides suggestions and plans but requires manual approval for all actions
|
||||
|
||||
**When should you use legacy mode?**
|
||||
|
||||
- If you prefer more control over what actions the AI takes
|
||||
- If you're concerned about security with automatic tool execution
|
||||
- If you want to manually review each step before applying changes
|
||||
|
||||
@@ -17,6 +17,9 @@ local Utils = require("avante.utils")
|
||||
|
||||
---@class avante.CoreConfig: avante.Config
|
||||
local M = {}
|
||||
|
||||
--- Default configuration for project-specific instruction file
|
||||
M.instructions_file = "avante.md"
|
||||
---@class avante.Config
|
||||
M._defaults = {
|
||||
debug = false,
|
||||
|
||||
@@ -8,6 +8,7 @@ local Utils = require("avante.utils")
|
||||
local Prompts = require("avante.utils.prompts")
|
||||
local Config = require("avante.config")
|
||||
local Path = require("avante.path")
|
||||
local PPath = require("plenary.path")
|
||||
local Providers = require("avante.providers")
|
||||
local LLMToolHelpers = require("avante.llm_tools.helpers")
|
||||
local LLMTools = require("avante.llm_tools")
|
||||
@@ -255,6 +256,17 @@ end
|
||||
---@param opts AvanteGeneratePromptsOptions
|
||||
---@return AvantePromptOptions
|
||||
function M.generate_prompts(opts)
|
||||
local project_instruction_file = Config.instructions_file or "avante.md"
|
||||
local project_root = Utils.root.get()
|
||||
local instruction_file_path = PPath:new(project_root, project_instruction_file)
|
||||
|
||||
if instruction_file_path:exists() then
|
||||
local lines = Utils.read_file_from_buf_or_disk(instruction_file_path:absolute())
|
||||
local instruction_content = lines and table.concat(lines, "\n") or ""
|
||||
|
||||
if instruction_content then opts.instructions = (opts.instructions or "") .. "\n" .. instruction_content end
|
||||
end
|
||||
|
||||
local provider = opts.provider or Providers[Config.provider]
|
||||
local mode = opts.mode or Config.mode
|
||||
|
||||
@@ -264,7 +276,6 @@ function M.generate_prompts(opts)
|
||||
image_paths = vim.list_extend(image_paths, opts.prompt_opts.image_paths)
|
||||
end
|
||||
|
||||
local project_root = Utils.root.get()
|
||||
Path.prompts.initialize(Path.prompts.get_templates_dir(project_root), project_root)
|
||||
|
||||
local system_info = Utils.get_system_info()
|
||||
|
||||
115
tests/llm_spec.lua
Normal file
115
tests/llm_spec.lua
Normal file
@@ -0,0 +1,115 @@
|
||||
local utils = require("avante.utils")
|
||||
local PPath = require("plenary.path")
|
||||
|
||||
local llm = require("avante.llm")
|
||||
|
||||
describe("generate_prompts", function()
|
||||
local project_root = "/tmp/project_root"
|
||||
|
||||
before_each(function()
|
||||
local mock_dir = PPath:new("tests", project_root)
|
||||
mock_dir:mkdir({ parents = true })
|
||||
|
||||
local mock_file = PPath:new("tests", project_root, "avante.md")
|
||||
mock_file:write("# Mock Instructions\nThis is a mock instruction file.", "w")
|
||||
|
||||
-- Mock the project root
|
||||
utils.root = {}
|
||||
utils.root.get = function() return mock_dir end
|
||||
|
||||
-- Mock Config.providers
|
||||
local Config = require("avante.config")
|
||||
Config.instructions_file = "avante.md"
|
||||
Config.provider = "openai"
|
||||
Config.providers = {
|
||||
openai = {
|
||||
endpoint = "https://api.mock.com/v1",
|
||||
model = "gpt-mock",
|
||||
timeout = 10000,
|
||||
context_window = 1000,
|
||||
extra_request_body = {
|
||||
temperature = 0.5,
|
||||
max_tokens = 1000,
|
||||
},
|
||||
},
|
||||
}
|
||||
-- Mock Config.history to prevent nil access error in Path.setup()
|
||||
Config.history = {
|
||||
max_tokens = 4096,
|
||||
carried_entry_count = nil,
|
||||
storage_path = "/tmp/test_avante_history",
|
||||
paste = {
|
||||
extension = "png",
|
||||
filename = "pasted-%Y-%m-%d-%H-%M-%S",
|
||||
},
|
||||
}
|
||||
|
||||
-- Mock Config.behaviour
|
||||
Config.behaviour = {
|
||||
auto_focus_sidebar = true,
|
||||
auto_suggestions = false, -- Experimental stage
|
||||
auto_suggestions_respect_ignore = false,
|
||||
auto_set_highlight_group = true,
|
||||
auto_set_keymaps = true,
|
||||
auto_apply_diff_after_generation = false,
|
||||
jump_result_buffer_on_finish = false,
|
||||
support_paste_from_clipboard = false,
|
||||
minimize_diff = true,
|
||||
enable_token_counting = true,
|
||||
use_cwd_as_project_root = false,
|
||||
auto_focus_on_diff_view = false,
|
||||
auto_approve_tool_permissions = false, -- Default: show permission prompts for all tools
|
||||
auto_check_diagnostics = true,
|
||||
enable_fastapply = false,
|
||||
}
|
||||
|
||||
-- Mock Config.rules to prevent nil access error in get_templates_dir()
|
||||
Config.rules = {
|
||||
project_dir = nil,
|
||||
global_dir = nil,
|
||||
}
|
||||
|
||||
-- Mock P.available to always return true
|
||||
local Path = require("avante.path")
|
||||
Path.available = function() return true end
|
||||
|
||||
-- Mock the Prompt functions directly since _templates_lib is a local variable
|
||||
-- that we can't easily access from outside the module
|
||||
Path.prompts.initialize = function(cache_directory, project_directory)
|
||||
-- Mock initialization - no-op for tests
|
||||
end
|
||||
|
||||
Path.prompts.render_file = function(path, opts)
|
||||
-- Mock render - return empty string for tests
|
||||
return ""
|
||||
end
|
||||
|
||||
Path.prompts.render_mode = function(mode, opts)
|
||||
-- Mock render_mode - return empty string for tests
|
||||
return ""
|
||||
end
|
||||
|
||||
Path.setup() -- Initialize necessary paths like cache_path
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
-- Clean up created test files and directories
|
||||
local mock_dir = PPath:new("tests", project_root)
|
||||
if mock_dir:exists() then mock_dir:rmdir() end
|
||||
end)
|
||||
|
||||
it("should include instruction file content when the file exists", function()
|
||||
local opts = {}
|
||||
llm.generate_prompts(opts)
|
||||
assert.are.same("\n# Mock Instructions\nThis is a mock instruction file.", opts.instructions)
|
||||
end)
|
||||
|
||||
it("should not modify instructions if the file does not exist", function()
|
||||
local mock_file = PPath:new("tests", project_root, "avante.md")
|
||||
if mock_file:exists() then mock_file:rm() end
|
||||
|
||||
local opts = {}
|
||||
llm.generate_prompts(opts)
|
||||
assert.are.same(opts.instructions, nil)
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user