Refactoring code
This commit is contained in:
@@ -4,80 +4,21 @@
|
||||
---@brief ]]
|
||||
|
||||
local Base = require("codetyper.agent.tools.base")
|
||||
local description = require("codetyper.prompts.agent.bash").description
|
||||
local params = require("codetyper.params.agent.bash").params
|
||||
local returns = require("codetyper.params.agent.bash").returns
|
||||
local BANNED_COMMANDS = require("codetyper.commands.agents.banned").BANNED_COMMANDS
|
||||
local BANNED_PATTERNS = require("codetyper.commands.agents.banned").BANNED_PATTERNS
|
||||
|
||||
---@class CoderTool
|
||||
local M = setmetatable({}, Base)
|
||||
|
||||
M.name = "bash"
|
||||
|
||||
M.description = [[Executes a bash command in a shell.
|
||||
|
||||
IMPORTANT RULES:
|
||||
- Do NOT use bash to read files (use 'view' tool instead)
|
||||
- Do NOT use bash to modify files (use 'write' or 'edit' tools instead)
|
||||
- Do NOT use interactive commands (vim, nano, less, etc.)
|
||||
- Commands timeout after 2 minutes by default
|
||||
|
||||
Allowed uses:
|
||||
- Running builds (make, npm run build, cargo build)
|
||||
- Running tests (npm test, pytest, cargo test)
|
||||
- Git operations (git status, git diff, git commit)
|
||||
- Package management (npm install, pip install)
|
||||
- System info commands (ls, pwd, which)]]
|
||||
|
||||
M.params = {
|
||||
{
|
||||
name = "command",
|
||||
description = "The shell command to execute",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "cwd",
|
||||
description = "Working directory for the command (optional)",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "timeout",
|
||||
description = "Timeout in milliseconds (default: 120000)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "stdout",
|
||||
description = "Command output",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if command failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.description = description
|
||||
M.params = params
|
||||
M.returns = returns
|
||||
M.requires_confirmation = true
|
||||
|
||||
--- Banned commands for safety
|
||||
local BANNED_COMMANDS = {
|
||||
"rm -rf /",
|
||||
"rm -rf /*",
|
||||
"dd if=/dev/zero",
|
||||
"mkfs",
|
||||
":(){ :|:& };:",
|
||||
"> /dev/sda",
|
||||
}
|
||||
|
||||
--- Banned patterns
|
||||
local BANNED_PATTERNS = {
|
||||
"curl.*|.*sh",
|
||||
"wget.*|.*sh",
|
||||
"rm%s+%-rf%s+/",
|
||||
}
|
||||
|
||||
--- Check if command is safe
|
||||
---@param command string
|
||||
---@return boolean safe
|
||||
|
||||
@@ -6,57 +6,17 @@
|
||||
---@brief ]]
|
||||
|
||||
local Base = require("codetyper.agent.tools.base")
|
||||
local description = require("codetyper.prompts.agent.edit").description
|
||||
local params = require("codetyper.params.agent.edit").params
|
||||
local returns = require("codetyper.params.agent.edit").returns
|
||||
|
||||
---@class CoderTool
|
||||
local M = setmetatable({}, Base)
|
||||
|
||||
M.name = "edit"
|
||||
|
||||
M.description = [[Makes a targeted edit to a file by replacing text.
|
||||
|
||||
The old_string should match the content you want to replace. The tool uses multiple
|
||||
matching strategies with fallbacks:
|
||||
1. Exact match
|
||||
2. Whitespace-normalized match
|
||||
3. Indentation-flexible match
|
||||
4. Line-trimmed match
|
||||
5. Fuzzy anchor-based match
|
||||
|
||||
For creating new files, use old_string="" and provide the full content in new_string.
|
||||
For large changes, consider using 'write' tool instead.]]
|
||||
|
||||
M.params = {
|
||||
{
|
||||
name = "path",
|
||||
description = "Path to the file to edit",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "old_string",
|
||||
description = "Text to find and replace (empty string to create new file or append)",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "new_string",
|
||||
description = "Text to replace with",
|
||||
type = "string",
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "success",
|
||||
description = "Whether the edit was applied",
|
||||
type = "boolean",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if edit failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.description = description
|
||||
M.params = params
|
||||
M.returns = returns
|
||||
M.requires_confirmation = false
|
||||
|
||||
--- Normalize line endings to LF
|
||||
@@ -211,11 +171,7 @@ local function levenshtein(s1, s2)
|
||||
for i = 1, len1 do
|
||||
for j = 1, len2 do
|
||||
local cost = s1:sub(i, i) == s2:sub(j, j) and 0 or 1
|
||||
matrix[i][j] = math.min(
|
||||
matrix[i - 1][j] + 1,
|
||||
matrix[i][j - 1] + 1,
|
||||
matrix[i - 1][j - 1] + cost
|
||||
)
|
||||
matrix[i][j] = math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -245,10 +201,13 @@ local function fuzzy_anchor_match(content, old_str, threshold)
|
||||
local candidates = {}
|
||||
for i, line in ipairs(content_lines) do
|
||||
local trimmed = line:match("^%s*(.-)%s*$")
|
||||
if trimmed == first_line or (
|
||||
#first_line > 0 and
|
||||
1 - (levenshtein(trimmed, first_line) / math.max(#trimmed, #first_line)) >= threshold
|
||||
) then
|
||||
if
|
||||
trimmed == first_line
|
||||
or (
|
||||
#first_line > 0
|
||||
and 1 - (levenshtein(trimmed, first_line) / math.max(#trimmed, #first_line)) >= threshold
|
||||
)
|
||||
then
|
||||
table.insert(candidates, i)
|
||||
end
|
||||
end
|
||||
@@ -258,10 +217,13 @@ local function fuzzy_anchor_match(content, old_str, threshold)
|
||||
local expected_end = start_idx + #old_lines - 1
|
||||
if expected_end <= #content_lines then
|
||||
local end_line = content_lines[expected_end]:match("^%s*(.-)%s*$")
|
||||
if end_line == last_line or (
|
||||
#last_line > 0 and
|
||||
1 - (levenshtein(end_line, last_line) / math.max(#end_line, #last_line)) >= threshold
|
||||
) then
|
||||
if
|
||||
end_line == last_line
|
||||
or (
|
||||
#last_line > 0
|
||||
and 1 - (levenshtein(end_line, last_line) / math.max(#end_line, #last_line)) >= threshold
|
||||
)
|
||||
then
|
||||
-- Calculate positions
|
||||
local before = table.concat(vim.list_slice(content_lines, 1, start_idx - 1), "\n")
|
||||
local block = table.concat(vim.list_slice(content_lines, start_idx, expected_end), "\n")
|
||||
|
||||
@@ -4,60 +4,17 @@
|
||||
---@brief ]]
|
||||
|
||||
local Base = require("codetyper.agent.tools.base")
|
||||
local description = require("codetyper.params.agent.grep").description
|
||||
local params = require("codetyper.prompts.agents.grep").params
|
||||
local returns = require("codetyper.prompts.agents.grep").returns
|
||||
|
||||
---@class CoderTool
|
||||
local M = setmetatable({}, Base)
|
||||
|
||||
M.name = "grep"
|
||||
|
||||
M.description = [[Searches for a pattern in files using ripgrep.
|
||||
|
||||
Returns file paths and matching lines. Use this to find code by content.
|
||||
|
||||
Example patterns:
|
||||
- "function foo" - Find function definitions
|
||||
- "import.*react" - Find React imports
|
||||
- "TODO|FIXME" - Find todo comments]]
|
||||
|
||||
M.params = {
|
||||
{
|
||||
name = "pattern",
|
||||
description = "Regular expression pattern to search for",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "path",
|
||||
description = "Directory or file to search in (default: project root)",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "include",
|
||||
description = "File glob pattern to include (e.g., '*.lua')",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "max_results",
|
||||
description = "Maximum number of results (default: 50)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "matches",
|
||||
description = "JSON array of matches with file, line_number, and content",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if search failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
M.description = description
|
||||
M.params = params
|
||||
M.returns = returns
|
||||
|
||||
M.requires_confirmation = false
|
||||
|
||||
|
||||
@@ -10,47 +10,12 @@ local M = setmetatable({}, Base)
|
||||
|
||||
M.name = "view"
|
||||
|
||||
M.description = [[Reads the content of a file.
|
||||
local params = require("codetyper.params.agent.view")
|
||||
local description = require("codetyper.prompts.agents.view").description
|
||||
|
||||
Usage notes:
|
||||
- Provide the file path relative to the project root
|
||||
- Use start_line and end_line to read specific sections
|
||||
- If content is truncated, use line ranges to read in chunks
|
||||
- Returns JSON with content, total_line_count, and is_truncated]]
|
||||
|
||||
M.params = {
|
||||
{
|
||||
name = "path",
|
||||
description = "Path to the file (relative to project root or absolute)",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "start_line",
|
||||
description = "Line number to start reading (1-indexed)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "end_line",
|
||||
description = "Line number to end reading (1-indexed, inclusive)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "content",
|
||||
description = "File contents as JSON with content, total_line_count, is_truncated",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if file could not be read",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
M.description = description
|
||||
M.params = params.params
|
||||
M.returns = params.returns
|
||||
|
||||
M.requires_confirmation = false
|
||||
|
||||
|
||||
@@ -4,45 +4,16 @@
|
||||
---@brief ]]
|
||||
|
||||
local Base = require("codetyper.agent.tools.base")
|
||||
local description = require("codetyper.prompts.agents.write").description
|
||||
local params = require("codetyper.params.agents.write")
|
||||
|
||||
---@class CoderTool
|
||||
local M = setmetatable({}, Base)
|
||||
|
||||
M.name = "write"
|
||||
|
||||
M.description = [[Creates or overwrites a file with new content.
|
||||
|
||||
IMPORTANT:
|
||||
- This will completely replace the file contents
|
||||
- Use 'edit' tool for partial modifications
|
||||
- Parent directories will be created if needed]]
|
||||
|
||||
M.params = {
|
||||
{
|
||||
name = "path",
|
||||
description = "Path to the file to write",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "content",
|
||||
description = "Content to write to the file",
|
||||
type = "string",
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "success",
|
||||
description = "Whether the file was written successfully",
|
||||
type = "boolean",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if write failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
M.description = description
|
||||
M.params = params.params
|
||||
M.returns = params.returns
|
||||
|
||||
M.requires_confirmation = true
|
||||
|
||||
|
||||
18
lua/codetyper/commands/agents/banned.lua
Normal file
18
lua/codetyper/commands/agents/banned.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
--- Banned commands for safety
|
||||
M.BANNED_COMMANDS = {
|
||||
"rm -rf /",
|
||||
"rm -rf /*",
|
||||
"dd if=/dev/zero",
|
||||
"mkfs",
|
||||
":(){ :|:& };:",
|
||||
"> /dev/sda",
|
||||
}
|
||||
|
||||
--- Banned patterns
|
||||
M.BANNED_PATTERNS = {
|
||||
"curl.*|.*sh",
|
||||
"wget.*|.*sh",
|
||||
"rm%s+%-rf%s+/",
|
||||
}
|
||||
|
||||
return M
|
||||
35
lua/codetyper/params/agent/bash.lua
Normal file
35
lua/codetyper/params/agent/bash.lua
Normal file
@@ -0,0 +1,35 @@
|
||||
M.params = {
|
||||
{
|
||||
name = "command",
|
||||
description = "The shell command to execute",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "cwd",
|
||||
description = "Working directory for the command (optional)",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "timeout",
|
||||
description = "Timeout in milliseconds (default: 120000)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "stdout",
|
||||
description = "Command output",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if command failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
33
lua/codetyper/params/agent/edit.lua
Normal file
33
lua/codetyper/params/agent/edit.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
M.params = {
|
||||
{
|
||||
name = "path",
|
||||
description = "Path to the file to edit",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "old_string",
|
||||
description = "Text to find and replace (empty string to create new file or append)",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "new_string",
|
||||
description = "Text to replace with",
|
||||
type = "string",
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "success",
|
||||
description = "Whether the edit was applied",
|
||||
type = "boolean",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if edit failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
10
lua/codetyper/params/agent/grep.lua
Normal file
10
lua/codetyper/params/agent/grep.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
M.description = [[Searches for a pattern in files using ripgrep.
|
||||
|
||||
Returns file paths and matching lines. Use this to find code by content.
|
||||
|
||||
Example patterns:
|
||||
- "function foo" - Find function definitions
|
||||
- "import.*react" - Find React imports
|
||||
- "TODO|FIXME" - Find todo comments]]
|
||||
|
||||
return M
|
||||
37
lua/codetyper/params/agent/view.lua
Normal file
37
lua/codetyper/params/agent/view.lua
Normal file
@@ -0,0 +1,37 @@
|
||||
local M = {}
|
||||
|
||||
M.params = {
|
||||
{
|
||||
name = "path",
|
||||
description = "Path to the file (relative to project root or absolute)",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "start_line",
|
||||
description = "Line number to start reading (1-indexed)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "end_line",
|
||||
description = "Line number to end reading (1-indexed, inclusive)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "content",
|
||||
description = "File contents as JSON with content, total_line_count, is_truncated",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if file could not be read",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
30
lua/codetyper/params/agents/write.lua
Normal file
30
lua/codetyper/params/agents/write.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local M = {}
|
||||
|
||||
M.params = {
|
||||
{
|
||||
name = "path",
|
||||
description = "Path to the file to write",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "content",
|
||||
description = "Content to write to the file",
|
||||
type = "string",
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "success",
|
||||
description = "Whether the file was written successfully",
|
||||
type = "boolean",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if write failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
16
lua/codetyper/prompts/agents/bash.lua
Normal file
16
lua/codetyper/prompts/agents/bash.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
M.description = [[Executes a bash command in a shell.
|
||||
|
||||
IMPORTANT RULES:
|
||||
- Do NOT use bash to read files (use 'view' tool instead)
|
||||
- Do NOT use bash to modify files (use 'write' or 'edit' tools instead)
|
||||
- Do NOT use interactive commands (vim, nano, less, etc.)
|
||||
- Commands timeout after 2 minutes by default
|
||||
|
||||
Allowed uses:
|
||||
- Running builds (make, npm run build, cargo build)
|
||||
- Running tests (npm test, pytest, cargo test)
|
||||
- Git operations (git status, git diff, git commit)
|
||||
- Package management (npm install, pip install)
|
||||
- System info commands (ls, pwd, which)]]
|
||||
|
||||
return M
|
||||
14
lua/codetyper/prompts/agents/edit.lua
Normal file
14
lua/codetyper/prompts/agents/edit.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
M.description = [[Makes a targeted edit to a file by replacing text.
|
||||
|
||||
The old_string should match the content you want to replace. The tool uses multiple
|
||||
matching strategies with fallbacks:
|
||||
1. Exact match
|
||||
2. Whitespace-normalized match
|
||||
3. Indentation-flexible match
|
||||
4. Line-trimmed match
|
||||
5. Fuzzy anchor-based match
|
||||
|
||||
For creating new files, use old_string="" and provide the full content in new_string.
|
||||
For large changes, consider using 'write' tool instead.]]
|
||||
|
||||
return M
|
||||
41
lua/codetyper/prompts/agents/grep.lua
Normal file
41
lua/codetyper/prompts/agents/grep.lua
Normal file
@@ -0,0 +1,41 @@
|
||||
M.params = {
|
||||
{
|
||||
name = "pattern",
|
||||
description = "Regular expression pattern to search for",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "path",
|
||||
description = "Directory or file to search in (default: project root)",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "include",
|
||||
description = "File glob pattern to include (e.g., '*.lua')",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
{
|
||||
name = "max_results",
|
||||
description = "Maximum number of results (default: 50)",
|
||||
type = "integer",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
M.returns = {
|
||||
{
|
||||
name = "matches",
|
||||
description = "JSON array of matches with file, line_number, and content",
|
||||
type = "string",
|
||||
},
|
||||
{
|
||||
name = "error",
|
||||
description = "Error message if search failed",
|
||||
type = "string",
|
||||
optional = true,
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
11
lua/codetyper/prompts/agents/view.lua
Normal file
11
lua/codetyper/prompts/agents/view.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
local M = {}
|
||||
|
||||
M.description = [[Reads the content of a file.
|
||||
|
||||
Usage notes:
|
||||
- Provide the file path relative to the project root
|
||||
- Use start_line and end_line to read specific sections
|
||||
- If content is truncated, use line ranges to read in chunks
|
||||
- Returns JSON with content, total_line_count, and is_truncated]]
|
||||
|
||||
return M
|
||||
8
lua/codetyper/prompts/agents/write.lua
Normal file
8
lua/codetyper/prompts/agents/write.lua
Normal file
@@ -0,0 +1,8 @@
|
||||
M.description = [[Creates or overwrites a file with new content.
|
||||
|
||||
IMPORTANT:
|
||||
- This will completely replace the file contents
|
||||
- Use 'edit' tool for partial modifications
|
||||
- Parent directories will be created if needed]]
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user