Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions codemcp/tools/chmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ async def chmod(
path: str,
mode: Literal["a+x", "a-x"],
chat_id: str | None = None,
signal=None,
) -> dict[str, Any]:
"""Change file permissions using chmod.

Args:
path: The absolute path to the file to modify
mode: The chmod mode to apply, only "a+x" and "a-x" are supported
chat_id: The unique ID of the current chat session
signal: Optional abort signal to terminate the subprocess

Returns:
A dictionary with chmod output
Expand Down Expand Up @@ -104,7 +102,7 @@ async def chmod(
success, commit_message = await commit_changes(
directory,
description,
chat_id,
chat_id if chat_id is not None else "",
)

if not success:
Expand Down
14 changes: 10 additions & 4 deletions codemcp/tools/edit_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import re
from difflib import SequenceMatcher
from typing import Any

from ..common import get_edit_snippet
from ..file_utils import (
Expand Down Expand Up @@ -53,7 +54,7 @@ async def apply_edit(
file_path: str,
old_string: str,
new_string: str,
) -> tuple[list[dict], str]:
) -> tuple[list[dict[str, Any]], str]:
"""Apply an edit to a file using robust matching strategies.

Args:
Expand Down Expand Up @@ -322,7 +323,7 @@ def try_dotdotdots(whole: str, part: str, replace: str) -> str | None:
part_pieces = [part_pieces[i] for i in range(0, len(part_pieces), 2)]
replace_pieces = [replace_pieces[i] for i in range(0, len(replace_pieces), 2)]

pairs = zip(part_pieces, replace_pieces, strict=False)
pairs = list(zip(part_pieces, replace_pieces))
for part, replace in pairs:
if not part and not replace:
continue
Expand Down Expand Up @@ -415,8 +416,13 @@ def find_similar_lines(
search_lines = search_lines.splitlines()
content_lines = content_lines.splitlines()

# Handle empty input cases
if not search_lines or not content_lines:
return ""

best_ratio = 0
best_match = None
best_match = [] # Initialize with empty list to avoid None checks
best_match_i = 0 # Initialize to avoid unbound variable errors

for i in range(len(content_lines) - len(search_lines) + 1):
chunk = content_lines[i : i + len(search_lines)]
Expand Down Expand Up @@ -730,7 +736,7 @@ async def edit_file_content(
)

# Apply the edit with advanced matching if needed
patch, updated_file = await apply_edit(full_file_path, old_string, new_string)
_, updated_file = await apply_edit(full_file_path, old_string, new_string)

# If no changes were made (which should never happen at this point),
# log a warning but continue
Expand Down
2 changes: 0 additions & 2 deletions codemcp/tools/git_blame.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,13 @@ async def git_blame(
arguments: str | None = None,
path: str | None = None,
chat_id: str | None = None,
signal=None,
) -> dict[str, Any]:
"""Execute git blame with the provided arguments.

Args:
arguments: Optional arguments to pass to git blame as a string
path: The directory to execute the command in (must be in a git repository)
chat_id: The unique ID of the current chat session
signal: Optional abort signal to terminate the subprocess

Returns:
A dictionary with git blame output
Expand Down
2 changes: 0 additions & 2 deletions codemcp/tools/git_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,13 @@ async def git_diff(
arguments: str | None = None,
path: str | None = None,
chat_id: str | None = None,
signal=None,
) -> dict[str, Any]:
"""Execute git diff with the provided arguments.

Args:
arguments: Optional arguments to pass to git diff as a string
path: The directory to execute the command in (must be in a git repository)
chat_id: The unique ID of the current chat session
signal: Optional abort signal to terminate the subprocess

Returns:
A dictionary with git diff output
Expand Down
2 changes: 0 additions & 2 deletions codemcp/tools/git_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,13 @@ async def git_log(
arguments: str | None = None,
path: str | None = None,
chat_id: str | None = None,
signal=None,
) -> dict[str, Any]:
"""Execute git log with the provided arguments.

Args:
arguments: Optional arguments to pass to git log as a string
path: The directory to execute the command in (must be in a git repository)
chat_id: The unique ID of the current chat session
signal: Optional abort signal to terminate the subprocess

Returns:
A dictionary with git log output
Expand Down
2 changes: 0 additions & 2 deletions codemcp/tools/git_show.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,13 @@ async def git_show(
arguments: str | None = None,
path: str | None = None,
chat_id: str | None = None,
signal=None,
) -> dict[str, Any]:
"""Execute git show with the provided arguments.

Args:
arguments: Optional arguments to pass to git show as a string
path: The directory to execute the command in (must be in a git repository)
chat_id: The unique ID of the current chat session
signal: Optional abort signal to terminate the subprocess

Returns:
A dictionary with git show output
Expand Down
6 changes: 1 addition & 5 deletions codemcp/tools/glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@ async def glob(
pattern: str,
path: str,
options: Optional[Dict[str, Any]] = None,
signal=None,
) -> Dict[str, Any]:
"""Find files matching a glob pattern.

Args:
pattern: The glob pattern to match files against
path: The directory to search in
options: Optional parameters for pagination (limit, offset)
signal: Optional abort signal to terminate the operation

Returns:
A dictionary with matched files and metadata
Expand Down Expand Up @@ -148,7 +146,6 @@ async def glob_files(
limit: int = MAX_RESULTS,
offset: int = 0,
chat_id: str | None = None,
signal=None,
) -> Dict[str, Any]:
"""Search for files matching a glob pattern.

Expand All @@ -158,7 +155,6 @@ async def glob_files(
limit: Maximum number of results to return
offset: Number of results to skip (for pagination)
chat_id: The unique ID of the current chat session
signal: Optional abort signal to terminate the operation

Returns:
A dictionary with matched files
Expand All @@ -174,7 +170,7 @@ async def glob_files(
}

# Execute glob
result = await glob(pattern, path, options, signal)
result = await glob(pattern, path, options)

# Get matching files
files = result.get("files", [])
Expand Down
8 changes: 2 additions & 6 deletions codemcp/tools/grep.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,13 @@ async def git_grep(
pattern: str,
path: str | None = None,
include: str | None = None,
signal=None,
) -> list[str]:
"""Execute git grep to search for pattern in files.

Args:
pattern: The regular expression pattern to search for
path: The directory or file to search in (must be in a git repository)
include: Optional file pattern to filter the search
signal: Optional abort signal to terminate the subprocess

Returns:
A list of file paths with matches
Expand Down Expand Up @@ -119,7 +117,7 @@ async def git_grep(
raise subprocess.SubprocessError(f"git grep failed: {result.stderr}")

# Process results - split by newline and filter empty lines
matches = [line.strip() for line in result.stdout.split("\n") if line.strip()]
matches = [line.strip() for line in result.stdout.split() if line.strip()]

# Convert to absolute paths
matches = [os.path.join(absolute_path, match) for match in matches]
Expand Down Expand Up @@ -160,7 +158,6 @@ async def grep_files(
path: str | None = None,
include: str | None = None,
chat_id: str | None = None,
signal=None,
) -> dict[str, Any]:
"""Search for a pattern in files within a directory or in a specific file.

Expand All @@ -169,15 +166,14 @@ async def grep_files(
path: The directory or file to search in (must be in a git repository)
include: Optional file pattern to filter the search
chat_id: The unique ID of the current chat session
signal: Optional abort signal to terminate the subprocess

Returns:
A dictionary with matched files

"""

# Execute git grep asynchronously
matches = await git_grep(pattern, path, include, signal)
matches = await git_grep(pattern, path, include)

# Sort matches
# Use asyncio for getting file stats
Expand Down
7 changes: 4 additions & 3 deletions codemcp/tools/init_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
import os
import re
from typing import Dict, Optional

import tomli

Expand Down Expand Up @@ -37,7 +38,7 @@ def _slugify(text: str) -> str:
return text[:50]


def _generate_command_docs(command_docs: dict) -> str:
def _generate_command_docs(command_docs: Dict[str, str]) -> str:
"""Generate documentation for commands from the command_docs dictionary.

Args:
Expand All @@ -56,7 +57,7 @@ def _generate_command_docs(command_docs: dict) -> str:
return "\n\nCommand documentation:" + "".join(docs)


async def _generate_chat_id(directory: str, description: str = None) -> str:
async def _generate_chat_id(directory: str, description: Optional[str] = None) -> str:
"""Generate a unique chat ID based on a counter stored in the git repository.

Args:
Expand Down Expand Up @@ -198,7 +199,7 @@ async def init_project(

# Create a commit reference instead of creating a regular commit
# This will not advance HEAD but store the commit in refs/codemcp/<chat_id>
message, commit_hash = await create_commit_reference(
_, _ = await create_commit_reference(
full_dir_path,
chat_id=chat_id,
commit_msg=commit_msg,
Expand Down
2 changes: 1 addition & 1 deletion codemcp/tools/rm.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
async def rm_file(
path: str,
description: str,
chat_id: str = None,
chat_id: str = "",
) -> str:
"""Remove a file using git rm.

Expand Down
7 changes: 5 additions & 2 deletions codemcp/tools/run_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ async def run_command(
project_dir: str,
command: str,
arguments: Optional[str] = None,
chat_id: str = None,
chat_id: str = "",
) -> str:
"""Run a command that is configured in codemcp.toml.

Expand All @@ -38,6 +38,9 @@ async def run_command(
parsed_args = shlex.split(arguments)
command_list.extend(parsed_args)

# Don't pass None to run_code_command
actual_command = command_list if command_list is not None else []

return await run_code_command(
project_dir, command, command_list, f"Auto-commit {command} changes", chat_id
project_dir, command, actual_command, f"Auto-commit {command} changes", chat_id
)
2 changes: 1 addition & 1 deletion codemcp/tools/write_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


async def write_file_content(
file_path: str, content: str, description: str = "", chat_id: str = None
file_path: str, content: str, description: str = "", chat_id: str = ""
) -> str:
"""Write content to a file.

Expand Down
Loading