From 9dfb52ac8d0b7fedafb9e1e5d099a8f543e70ada Mon Sep 17 00:00:00 2001 From: Carlos Gutierrez Date: Fri, 16 Jan 2026 10:45:34 -0500 Subject: [PATCH] Refactoring code --- lua/codetyper/agent/tools/bash.lua | 75 +++------------------- lua/codetyper/agent/tools/edit.lua | 80 +++++++----------------- lua/codetyper/agent/tools/grep.lua | 55 ++-------------- lua/codetyper/agent/tools/view.lua | 45 ++----------- lua/codetyper/agent/tools/write.lua | 39 ++---------- lua/codetyper/commands/agents/banned.lua | 18 ++++++ lua/codetyper/params/agent/bash.lua | 35 +++++++++++ lua/codetyper/params/agent/edit.lua | 33 ++++++++++ lua/codetyper/params/agent/grep.lua | 10 +++ lua/codetyper/params/agent/view.lua | 37 +++++++++++ lua/codetyper/params/agents/write.lua | 30 +++++++++ lua/codetyper/prompts/agents/bash.lua | 16 +++++ lua/codetyper/prompts/agents/edit.lua | 14 +++++ lua/codetyper/prompts/agents/grep.lua | 41 ++++++++++++ lua/codetyper/prompts/agents/view.lua | 11 ++++ lua/codetyper/prompts/agents/write.lua | 8 +++ 16 files changed, 298 insertions(+), 249 deletions(-) create mode 100644 lua/codetyper/commands/agents/banned.lua create mode 100644 lua/codetyper/params/agent/bash.lua create mode 100644 lua/codetyper/params/agent/edit.lua create mode 100644 lua/codetyper/params/agent/grep.lua create mode 100644 lua/codetyper/params/agent/view.lua create mode 100644 lua/codetyper/params/agents/write.lua create mode 100644 lua/codetyper/prompts/agents/bash.lua create mode 100644 lua/codetyper/prompts/agents/edit.lua create mode 100644 lua/codetyper/prompts/agents/grep.lua create mode 100644 lua/codetyper/prompts/agents/view.lua create mode 100644 lua/codetyper/prompts/agents/write.lua diff --git a/lua/codetyper/agent/tools/bash.lua b/lua/codetyper/agent/tools/bash.lua index 4730584..7421209 100644 --- a/lua/codetyper/agent/tools/bash.lua +++ b/lua/codetyper/agent/tools/bash.lua @@ -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 diff --git a/lua/codetyper/agent/tools/edit.lua b/lua/codetyper/agent/tools/edit.lua index 6e7a11b..8a485f2 100644 --- a/lua/codetyper/agent/tools/edit.lua +++ b/lua/codetyper/agent/tools/edit.lua @@ -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") diff --git a/lua/codetyper/agent/tools/grep.lua b/lua/codetyper/agent/tools/grep.lua index b1396df..1f34b97 100644 --- a/lua/codetyper/agent/tools/grep.lua +++ b/lua/codetyper/agent/tools/grep.lua @@ -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 diff --git a/lua/codetyper/agent/tools/view.lua b/lua/codetyper/agent/tools/view.lua index 8e52feb..a3eb641 100644 --- a/lua/codetyper/agent/tools/view.lua +++ b/lua/codetyper/agent/tools/view.lua @@ -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 diff --git a/lua/codetyper/agent/tools/write.lua b/lua/codetyper/agent/tools/write.lua index e410a56..946a1bb 100644 --- a/lua/codetyper/agent/tools/write.lua +++ b/lua/codetyper/agent/tools/write.lua @@ -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 diff --git a/lua/codetyper/commands/agents/banned.lua b/lua/codetyper/commands/agents/banned.lua new file mode 100644 index 0000000..ad5eadc --- /dev/null +++ b/lua/codetyper/commands/agents/banned.lua @@ -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 diff --git a/lua/codetyper/params/agent/bash.lua b/lua/codetyper/params/agent/bash.lua new file mode 100644 index 0000000..5a81e86 --- /dev/null +++ b/lua/codetyper/params/agent/bash.lua @@ -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 diff --git a/lua/codetyper/params/agent/edit.lua b/lua/codetyper/params/agent/edit.lua new file mode 100644 index 0000000..3f353cd --- /dev/null +++ b/lua/codetyper/params/agent/edit.lua @@ -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 diff --git a/lua/codetyper/params/agent/grep.lua b/lua/codetyper/params/agent/grep.lua new file mode 100644 index 0000000..b977a46 --- /dev/null +++ b/lua/codetyper/params/agent/grep.lua @@ -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 diff --git a/lua/codetyper/params/agent/view.lua b/lua/codetyper/params/agent/view.lua new file mode 100644 index 0000000..64d2d4e --- /dev/null +++ b/lua/codetyper/params/agent/view.lua @@ -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 \ No newline at end of file diff --git a/lua/codetyper/params/agents/write.lua b/lua/codetyper/params/agents/write.lua new file mode 100644 index 0000000..60a71b4 --- /dev/null +++ b/lua/codetyper/params/agents/write.lua @@ -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 \ No newline at end of file diff --git a/lua/codetyper/prompts/agents/bash.lua b/lua/codetyper/prompts/agents/bash.lua new file mode 100644 index 0000000..db10d83 --- /dev/null +++ b/lua/codetyper/prompts/agents/bash.lua @@ -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 diff --git a/lua/codetyper/prompts/agents/edit.lua b/lua/codetyper/prompts/agents/edit.lua new file mode 100644 index 0000000..2603a83 --- /dev/null +++ b/lua/codetyper/prompts/agents/edit.lua @@ -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 diff --git a/lua/codetyper/prompts/agents/grep.lua b/lua/codetyper/prompts/agents/grep.lua new file mode 100644 index 0000000..9713c41 --- /dev/null +++ b/lua/codetyper/prompts/agents/grep.lua @@ -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 diff --git a/lua/codetyper/prompts/agents/view.lua b/lua/codetyper/prompts/agents/view.lua new file mode 100644 index 0000000..7f38e4c --- /dev/null +++ b/lua/codetyper/prompts/agents/view.lua @@ -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 \ No newline at end of file diff --git a/lua/codetyper/prompts/agents/write.lua b/lua/codetyper/prompts/agents/write.lua new file mode 100644 index 0000000..d15b87b --- /dev/null +++ b/lua/codetyper/prompts/agents/write.lua @@ -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