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.
|
- **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.
|
- **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
|
## Installation
|
||||||
|
|
||||||
@@ -84,6 +85,8 @@ For building binary if you wish to build from source, then `cargo` is required.
|
|||||||
---@type avante.Config
|
---@type avante.Config
|
||||||
opts = {
|
opts = {
|
||||||
-- add any opts here
|
-- add any opts here
|
||||||
|
-- this file can containe specific instructions for your project
|
||||||
|
instructions_file = "avante.md"
|
||||||
-- for example
|
-- for example
|
||||||
provider = "claude",
|
provider = "claude",
|
||||||
providers = {
|
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:
|
Avante.nvim provides several completion sources that can be integrated with blink.cmp:
|
||||||
|
|
||||||
#### Mentions (`@` trigger)
|
#### Mentions (`@` trigger)
|
||||||
|
|
||||||
Mentions allow you to quickly reference specific features or add files to the chat context:
|
Mentions allow you to quickly reference specific features or add files to the chat context:
|
||||||
|
|
||||||
- `@codebase` - Enable project context and repository mapping
|
- `@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
|
- `@buffers` - Add open buffers to chat context
|
||||||
|
|
||||||
#### Slash Commands (`/` trigger)
|
#### Slash Commands (`/` trigger)
|
||||||
|
|
||||||
Built-in slash commands for common operations:
|
Built-in slash commands for common operations:
|
||||||
|
|
||||||
- `/help` - Show help message with available commands
|
- `/help` - Show help message with available commands
|
||||||
@@ -676,6 +681,7 @@ Built-in slash commands for common operations:
|
|||||||
- `/commit` - Generate commit message for changes
|
- `/commit` - Generate commit message for changes
|
||||||
|
|
||||||
#### Shortcuts (`#` trigger)
|
#### Shortcuts (`#` trigger)
|
||||||
|
|
||||||
Shortcuts provide quick access to predefined prompt templates. You can customize these in your config:
|
Shortcuts provide quick access to predefined prompt templates. You can customize these in your config:
|
||||||
|
|
||||||
```lua
|
```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.
|
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:
|
Key benefits:
|
||||||
|
|
||||||
- **Instant application**: Code changes are applied immediately without noticeable delays
|
- **Instant application**: Code changes are applied immediately without noticeable delays
|
||||||
- **High accuracy**: Specialized models achieve 96-98% accuracy for code edits
|
- **High accuracy**: Specialized models achieve 96-98% accuracy for code edits
|
||||||
- **Seamless workflow**: Maintains the natural flow of development without interruptions
|
- **Seamless workflow**: Maintains the natural flow of development without interruptions
|
||||||
@@ -993,6 +1000,7 @@ Key benefits:
|
|||||||
To enable Fast Apply, you need to:
|
To enable Fast Apply, you need to:
|
||||||
|
|
||||||
1. **Enable Fast Apply in your configuration**:
|
1. **Enable Fast Apply in your configuration**:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
behaviour = {
|
behaviour = {
|
||||||
enable_fastapply = true, -- Enable Fast Apply feature
|
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.
|
Go to [morphllm.com](https://morphllm.com/api-keys) and create an account and get the API key.
|
||||||
|
|
||||||
3. **Set your Morph API key**:
|
3. **Set your Morph API key**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export MORPH_API_KEY="your-api-key"
|
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:
|
Morph provides different models optimized for different use cases:
|
||||||
|
|
||||||
| Model | Speed | Accuracy | Context Limit |
|
| Model | Speed | Accuracy | Context Limit |
|
||||||
|-------|-------|----------|---------------|
|
| ---------------- | ----------------- | -------- | ------------- |
|
||||||
| `morph-v3-fast` | 4500+ tok/sec | 96% | 16k tokens |
|
| `morph-v3-fast` | 4500+ tok/sec | 96% | 16k tokens |
|
||||||
| `morph-v3-large` | 2500+ tok/sec | 98% | 16k tokens |
|
| `morph-v3-large` | 2500+ tok/sec | 98% | 16k tokens |
|
||||||
| `auto` | 2500-4500 tok/sec | 98% | 16k tokens |
|
| `auto` | 2500-4500 tok/sec | 98% | 16k tokens |
|
||||||
|
|
||||||
### How It Works
|
### 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
|
4. Apply the changes directly to your files with high accuracy
|
||||||
|
|
||||||
The process uses a specialized prompt format that includes:
|
The process uses a specialized prompt format that includes:
|
||||||
|
|
||||||
- `<instructions>`: Clear description of what changes to make
|
- `<instructions>`: Clear description of what changes to make
|
||||||
- `<code>`: The original code content
|
- `<code>`: The original code content
|
||||||
- `<update>`: The specific changes using truncation markers (`// ... existing code ...`)
|
- `<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?
|
### How to disable agentic mode?
|
||||||
|
|
||||||
Avante.nvim provides two interaction modes:
|
Avante.nvim provides two interaction modes:
|
||||||
|
|
||||||
- **`agentic`** (default): Uses AI tools to automatically generate and apply code changes
|
- **`agentic`** (default): Uses AI tools to automatically generate and apply code changes
|
||||||
- **`legacy`**: Uses the traditional planning method without automatic tool execution
|
- **`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?**
|
**What's the difference?**
|
||||||
|
|
||||||
- **Agentic mode**: AI can automatically execute tools like file operations, bash commands, web searches, etc. to complete complex tasks
|
- **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
|
- **Legacy mode**: AI provides suggestions and plans but requires manual approval for all actions
|
||||||
|
|
||||||
**When should you use legacy mode?**
|
**When should you use legacy mode?**
|
||||||
|
|
||||||
- If you prefer more control over what actions the AI takes
|
- If you prefer more control over what actions the AI takes
|
||||||
- If you're concerned about security with automatic tool execution
|
- If you're concerned about security with automatic tool execution
|
||||||
- If you want to manually review each step before applying changes
|
- 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
|
---@class avante.CoreConfig: avante.Config
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
--- Default configuration for project-specific instruction file
|
||||||
|
M.instructions_file = "avante.md"
|
||||||
---@class avante.Config
|
---@class avante.Config
|
||||||
M._defaults = {
|
M._defaults = {
|
||||||
debug = false,
|
debug = false,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ local Utils = require("avante.utils")
|
|||||||
local Prompts = require("avante.utils.prompts")
|
local Prompts = require("avante.utils.prompts")
|
||||||
local Config = require("avante.config")
|
local Config = require("avante.config")
|
||||||
local Path = require("avante.path")
|
local Path = require("avante.path")
|
||||||
|
local PPath = require("plenary.path")
|
||||||
local Providers = require("avante.providers")
|
local Providers = require("avante.providers")
|
||||||
local LLMToolHelpers = require("avante.llm_tools.helpers")
|
local LLMToolHelpers = require("avante.llm_tools.helpers")
|
||||||
local LLMTools = require("avante.llm_tools")
|
local LLMTools = require("avante.llm_tools")
|
||||||
@@ -255,6 +256,17 @@ end
|
|||||||
---@param opts AvanteGeneratePromptsOptions
|
---@param opts AvanteGeneratePromptsOptions
|
||||||
---@return AvantePromptOptions
|
---@return AvantePromptOptions
|
||||||
function M.generate_prompts(opts)
|
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 provider = opts.provider or Providers[Config.provider]
|
||||||
local mode = opts.mode or Config.mode
|
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)
|
image_paths = vim.list_extend(image_paths, opts.prompt_opts.image_paths)
|
||||||
end
|
end
|
||||||
|
|
||||||
local project_root = Utils.root.get()
|
|
||||||
Path.prompts.initialize(Path.prompts.get_templates_dir(project_root), project_root)
|
Path.prompts.initialize(Path.prompts.get_templates_dir(project_root), project_root)
|
||||||
|
|
||||||
local system_info = Utils.get_system_info()
|
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