Skip to content
Merged
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
102 changes: 102 additions & 0 deletions integration_tests/test_edit_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import subprocess
import time
import sys
import os


def run_integration_test():
print("🚀 Starting Integration Test for 'edit' tool...")

# Ensure current directory is in PYTHONPATH for the subprocess
env = os.environ.copy()
env["PYTHONPATH"] = os.getcwd() + ":" + env.get("PYTHONPATH", "")

# Create a test file
test_filename = "test_edit_integration.txt"
with open(test_filename, "w") as f:
f.write("Line 1\nLine 2\nLine 3\n")

# Start the mini-copilot process
process = subprocess.Popen(
[sys.executable, "-m", "mini_copilot.main"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
cwd=os.getcwd(),
env=env,
)

try:
# 1. Wait for prompt
print("Waiting for prompt...")
output = ""
start_time = time.time()
while time.time() - start_time < 30:
char = process.stdout.read(1)
if not char:
break
output += char
if "> " in output:
print("✅ Prompt detected.")
break

if "> " not in output:
print(f"❌ Timed out waiting for prompt. Last output: {output}")
return False

# 2. Trigger tool
print(f"Sending message to trigger 'edit' tool on {test_filename}...")
edit_request = f"Edit the file {test_filename}. Change 'Line 2' to 'Line Two'.\n"
process.stdin.write(edit_request)
process.stdin.flush()

# 3. Look for tool execution
print("Monitoring for tool invocation and response...")
found_tool = False
found_success = False
start_time = time.time()
output = ""
while time.time() - start_time < 60:
char = process.stdout.read(1)
if not char:
break
output += char
sys.stdout.write(char)
sys.stdout.flush()

if f"Successfully edited {test_filename}" in output:
found_tool = True

# If the assistant replies and we found the tool message, we are good
if found_tool and "> " in output:
found_success = True
break

if found_tool:
# Verify file content
with open(test_filename, "r") as f:
content = f.read()
if "Line Two" in content and "Line 2" not in content:
print(f"\n✅ File content verified: {test_filename}")
print("\n🎉 Integration Test PASSED!")
return True
else:
print(f"\n❌ File content mismatch. Content: {content}")
return False
else:
print("\n❌ Integration Test FAILED (Tool not triggered or response not found).")
return False

finally:
process.terminate()
if os.path.exists(test_filename):
os.remove(test_filename)


if __name__ == "__main__":
if run_integration_test():
sys.exit(0)
else:
sys.exit(1)
42 changes: 41 additions & 1 deletion mini_copilot/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def completer(text, state):
from mini_copilot.github_api import chat, get_copilot_token
from mini_copilot.web_search import web_search
from mini_copilot.exec_tool import exec_command as exec
from tools.edit_tool import EditTool
from mini_copilot.commands.auth import handle_login_command
from mini_copilot.commands.model import handle_model_command
from mini_copilot.commands.search_provider import handle_search_provider_command
Expand Down Expand Up @@ -78,7 +79,29 @@ def completer(text, state):
},
},
}
TOOLS = [WEB_SEARCH_TOOL, EXEC_COMMAND_TOOL]

EDIT_TOOL = {
"type": "function",
"function": {
"name": "edit",
"description": "Apply a unified diff edit to a file on the local system.",
"parameters": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "The path to the file to edit.",
},
"edit_content": {
"type": "string",
"description": "The unified diff content to apply.",
},
},
"required": ["file_path", "edit_content"],
},
},
}
TOOLS = [WEB_SEARCH_TOOL, EXEC_COMMAND_TOOL, EDIT_TOOL]


def load_github_token():
Expand Down Expand Up @@ -199,6 +222,23 @@ def main():
"content": output,
}
)

if function_name == "edit":
file_path = function_args.get("file_path")
edit_content = function_args.get("edit_content")

result = EditTool.edit(file_path, edit_content)
with open(file_path, "w") as f:
f.write(result)

messages.append(
{
"tool_call_id": tool_call["id"],
"role": "tool",
"name": function_name,
"content": f"Successfully edited {file_path}",
}
)
response_message = chat(
messages, copilot_token, current_model, tools=TOOLS
)
Expand Down
Loading