diff --git a/README.md b/README.md
index c0df3bd..00150f9 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-

+

@@ -48,7 +48,7 @@ AgentTide consists of a demo, showing how CodeTide can integrate with LLMs and a
-

+
---
diff --git a/codetide/mcp/tools/patch_code/__init__.py b/codetide/mcp/tools/patch_code/__init__.py
index c9a623c..59f96b4 100644
--- a/codetide/mcp/tools/patch_code/__init__.py
+++ b/codetide/mcp/tools/patch_code/__init__.py
@@ -25,7 +25,7 @@ def text_to_patch(text: str, orig: Dict[str, str]) -> Tuple[Patch, int]:
elif (line.startswith("---") and len(line) == 3) or not line.startswith(("+", "-", " ")):
lines[i] = f" {line}"
- elif line.startswith(("+", "-")) and i + 1 < len(lines) and lines[i+1].startswith(" "):
+ elif line.startswith(("+", "-")) and 1 < i + 1 < len(lines) and lines[i+1].startswith(" ") and not lines[i-1].startswith(("+", "-")) and lines[i+1].strip():
lines[i] = f" {line}"
# Debug output
diff --git a/examples/hf_demo_space/api.py b/examples/hf_demo_space/api.py
index fcc97b9..5329cd1 100644
--- a/examples/hf_demo_space/api.py
+++ b/examples/hf_demo_space/api.py
@@ -54,6 +54,26 @@ async def logo_dark():
# Return 204 No Content if favicon doesn't exist
return HTMLResponse(status_code=204)
+@app.get("/codetide-banner.png", include_in_schema=False)
+async def codetide_banner():
+ """Serve favicon"""
+ favicon_path = Path(F"{ROOT_PATH}/public/codetide-banner.png")
+ if favicon_path.exists():
+ return FileResponse(favicon_path)
+ else:
+ # Return 204 No Content if favicon doesn't exist
+ return HTMLResponse(status_code=204)
+
+@app.get("/agent-tide-demo.gif", include_in_schema=False)
+async def agent_tide_deo_gif():
+ """Serve favicon"""
+ favicon_path = Path(F"{ROOT_PATH}/public/agent-tide-demo.gif")
+ if favicon_path.exists():
+ return FileResponse(favicon_path)
+ else:
+ # Return 204 No Content if favicon doesn't exist
+ return HTMLResponse(status_code=204)
+
mount_chainlit(app=app, target=F"{ROOT_PATH}/app.py", path="/tide")
if __name__ == "__main__":
diff --git a/tests/mcp/tools/test_apply_patch.py b/tests/mcp/tools/test_apply_patch.py
index 01ec503..1e6203c 100644
--- a/tests/mcp/tools/test_apply_patch.py
+++ b/tests/mcp/tools/test_apply_patch.py
@@ -487,4 +487,390 @@ def test_error_move_to_existing_file(mock_fs):
*** End Patch
"""
with pytest.raises(DiffError, match="Cannot move 'utils.py' to 'main.py' because the target file already exists"):
- mock_fs.apply_patch(patch)
\ No newline at end of file
+ mock_fs.apply_patch(patch)
+
+def test_update_with_context_after_changes(mock_fs):
+ """Test update with context lines appearing after the changes"""
+ patch = """*** Begin Patch
+*** Update File: main.py
+@@ def hello():
+- print('Hello, world!')
++ print('Greetings, universe!')
+
+ def goodbye():
+*** End Patch
+"""
+ mock_fs.apply_patch(patch)
+ content = mock_fs.read_file('main.py')
+ assert "Greetings, universe!" in content
+ assert "Hello, world!" not in content
+ # Verify the context after changes is preserved
+ assert "def goodbye():" in content
+
+
+def test_update_with_context_before_and_after(mock_fs):
+ """Test update with context lines both before and after the changes"""
+ patch = """*** Begin Patch
+*** Update File: main.py
+@@ def hello():
+ def hello():
+- print('Hello, world!')
++ print('Hi there!')
+
+ def goodbye():
+ print('Goodbye, world!')
+*** End Patch
+"""
+ mock_fs.apply_patch(patch)
+ content = mock_fs.read_file('main.py')
+ assert "Hi there!" in content
+ assert "Hello, world!" not in content
+ # Verify both before and after context is preserved
+ assert "def hello():" in content
+ assert "def goodbye():" in content
+ assert "Goodbye, world!" in content
+
+
+def test_multiple_changes_with_trailing_context(mock_fs):
+ """Test multiple change blocks each followed by context lines"""
+ patch = """*** Begin Patch
+*** Update File: main.py
+@@ def hello():
+- print('Hello, world!')
++ print('Howdy!')
+
+ def goodbye():
+- print('Goodbye, world!')
++ print('See ya!')
+
+if __name__ == '__main__':
+*** End Patch
+"""
+ mock_fs.apply_patch(patch)
+ content = mock_fs.read_file('main.py')
+ assert "Howdy!" in content
+ assert "See ya!" in content
+ assert "Hello, world!" not in content
+ assert "Goodbye, world!" not in content
+ # Verify trailing context is preserved
+ assert "if __name__ == '__main__':" in content
+
+def test_complex_multi_section_with_mixed_context(mock_fs):
+ """Test multiple sections with complex context patterns and edge cases"""
+ # Create a more complex file to work with
+ mock_fs._create_file('complex.py', (
+ "# Header comment\n"
+ "import sys\n"
+ "import os\n"
+ "\n"
+ "class MyClass:\n"
+ " def __init__(self):\n"
+ " self.value = 0\n"
+ "\n"
+ " def method_one(self):\n"
+ " return self.value\n"
+ "\n"
+ " def method_two(self):\n"
+ " self.value += 1\n"
+ "\n"
+ "def global_func():\n"
+ " return 'original'\n"
+ "\n"
+ "if __name__ == '__main__':\n"
+ " obj = MyClass()\n"
+ " print(obj.method_one())\n"
+ ))
+
+ patch = """*** Begin Patch
+*** Update File: complex.py
+@@ import sys
+ import sys
+-import os
++import json
++import logging
+
+ class MyClass:
+@@ def method_one(self):
+- return self.value
++ # Enhanced method with logging
++ logging.info("Getting value")
++ return self.value * 2
+
+ def method_two(self):
+@@ def global_func():
+- return 'original'
++ return 'modified'
++
++def new_global_func():
++ return 'brand new'
+
+ if __name__ == '__main__':
+*** End Patch
+"""
+ mock_fs.apply_patch(patch)
+ content = mock_fs.read_file('complex.py')
+
+ # Verify all changes applied correctly
+ assert "import json" in content
+ assert "import logging" in content
+ assert "import os" not in content
+ assert "logging.info(\"Getting value\")" in content
+ assert "return self.value * 2" in content
+ assert "return 'modified'" in content
+ assert "def new_global_func():" in content
+ assert "return 'brand new'" in content
+
+
+def test_nested_indentation_and_whitespace_sensitivity(mock_fs):
+ """Test complex indentation patterns and whitespace-sensitive changes"""
+ mock_fs._create_file('indented.py', (
+ "def outer():\n"
+ " if True:\n"
+ " def inner():\n"
+ " x = 1\n"
+ " y = 2\n"
+ " return x + y\n"
+ " return inner()\n"
+ " else:\n"
+ " return None\n"
+ ))
+
+ patch = """*** Begin Patch
+*** Update File: indented.py
+@@ def inner():
+ def inner():
+- x = 1
+- y = 2
+- return x + y
++ # More complex calculation
++ x, y = 1, 2
++ z = x * y
++ return x + y + z
+ return inner()
+@@ else:
+ else:
+- return None
++ # Better default handling
++ return 0
+*** End Patch
+"""
+ mock_fs.apply_patch(patch)
+ content = mock_fs.read_file('indented.py')
+
+ assert "# More complex calculation" in content
+ assert "x, y = 1, 2" in content
+ assert "z = x * y" in content
+ assert "return x + y + z" in content
+ assert "# Better default handling" in content
+ assert "return 0" in content
+ assert "return None" not in content
+
+
+def test_edge_case_empty_lines_and_special_characters(mock_fs):
+ """Test handling of empty lines, special characters, and edge cases"""
+ mock_fs._create_file('special.py', (
+ "#!/usr/bin/env python3\n"
+ "# -*- coding: utf-8 -*-\n"
+ "\n"
+ "import re\n"
+ "\n"
+ "def parse_string(text):\n"
+ " # Handle quotes and escapes\n"
+ " pattern = r'\".*?\"'\n"
+ " return re.findall(pattern, text)\n"
+ "\n"
+ "\n"
+ "def main():\n"
+ " pass\n"
+ ))
+
+ patch = """*** Begin Patch
+*** Update File: special.py
+@@ #!/usr/bin/env python3
+ #!/usr/bin/env python3
+-# -*- coding: utf-8 -*-
++# -*- coding: utf-8 -*-
++# Author: Test Suite
+
+
+ import re
+@@ def parse_string(text):
+ # Handle quotes and escapes
+- pattern = r'\".*?\"'
+- return re.findall(pattern, text)
++ # Updated regex pattern with better handling
++ pattern = r'\"([^\"\\\\]|\\\\.)*?\"'
++ matches = re.findall(pattern, text)
++ return [m.strip('\"') for m in matches]
+
+
+@@ def main():
+- pass
++ test_text = 'He said \"Hello, world!\"'
++ results = parse_string(test_text)
++ print(f"Found: {results}")
+*** End of File
+*** End Patch
+"""
+ mock_fs.apply_patch(patch)
+ content = mock_fs.read_file('special.py')
+
+ assert "# Author: Test Suite" in content
+ assert 'r\'\"([^\"\\\\]|\\\\.)*?\"' in content
+ assert "test_text = 'He said \"Hello, world!\"'" in content
+ assert "Found: {results}" in content
+ assert "pass" not in content
+
+
+def test_complex_file_operations_with_dependencies(mock_fs):
+ """Test complex scenario with add, update, move, and delete operations"""
+ # Create additional files for this complex scenario
+ mock_fs._create_file('config.py', (
+ "DEBUG = True\n"
+ "VERSION = '1.0.0'\n"
+ "DATABASE_URL = 'sqlite:///app.db'\n"
+ ))
+
+ mock_fs._create_file('models.py', (
+ "from config import DATABASE_URL\n"
+ "\n"
+ "class User:\n"
+ " def __init__(self, name):\n"
+ " self.name = name\n"
+ ))
+
+ patch = '''*** Begin Patch
+*** Add File: settings/__init__.py
++# Settings package
+
+*** Add File: settings/base.py
++"""Base settings module"""
++
++# Core configuration
++DEBUG = False
++VERSION = '2.0.0'
++
++# Database settings
++DATABASE_CONFIG = {
++ 'url': 'postgresql://localhost/app',
++ 'pool_size': 10
++}
+
+*** Update File: config.py
+*** Move to: settings/legacy_config.py
+@@ DEBUG = True
+-DEBUG = True
++# Legacy debug setting - deprecated
++DEBUG = True # TODO: Remove this
+ VERSION = '1.0.0'
+-DATABASE_URL = 'sqlite:///app.db'
++# Old database URL - migrated to base.py
++DATABASE_URL = 'sqlite:///app.db' # DEPRECATED
+*** End of File
+
+*** Update File: models.py
+@@ from config import DATABASE_URL
+-from config import DATABASE_URL
++from settings.base import DATABASE_CONFIG
+
+ class User:
+@@ def __init__(self, name):
+ def __init__(self, name):
+ self.name = name
++ self.id = None
++
++ def save(self):
++ # TODO: Implement database save
++ pass
+
+*** Delete File: empty.txt
+*** End Patch
+'''
+
+ mock_fs.apply_patch(patch)
+
+ # Verify all operations
+ assert mock_fs.file_exists('settings/__init__.py')
+ assert mock_fs.file_exists('settings/base.py')
+ assert mock_fs.file_exists('settings/legacy_config.py')
+ assert not mock_fs.file_exists('config.py')
+ assert not mock_fs.file_exists('empty.txt')
+
+ # Verify content changes
+ settings_content = mock_fs.read_file('settings/base.py')
+ assert "DATABASE_CONFIG = {" in settings_content
+ assert "'pool_size': 10" in settings_content
+
+ legacy_content = mock_fs.read_file('settings/legacy_config.py')
+ assert "# Legacy debug setting - deprecated" in legacy_content
+ assert "# DEPRECATED" in legacy_content
+
+ models_content = mock_fs.read_file('models.py')
+ assert "from settings.base import DATABASE_CONFIG" in models_content
+ assert "self.id = None" in models_content
+ assert "def save(self):" in models_content
+ assert "from config import DATABASE_URL" not in models_content
+
+
+def test_boundary_conditions_and_fuzzy_matching_limits(mock_fs):
+ """Test boundary conditions for fuzzy matching and context finding"""
+ mock_fs._create_file('boundary.py', (
+ "# Very similar lines that test fuzzy matching limits\n"
+ "def function_a():\n"
+ " x=1\n"
+ " y=2\n"
+ " return x+y\n"
+ "\n"
+ "def function_b():\n"
+ " x = 1\n"
+ " y = 2 \n"
+ " return x + y\n"
+ "\n"
+ "def function_c():\n"
+ " x = 1\n"
+ " y = 2\n"
+ " return x + y\n"
+ ))
+
+ patch = """*** Begin Patch
+*** Update File: boundary.py
+@@ def function_a():
+ def function_a():
+- x=1
+- y=2
+- return x+y
++ # Tight spacing version
++ a=10
++ b=20
++ return a*b
+
+ def function_b():
+@@ def function_c():
+ x = 1
+- y = 2
+- return x + y
++ # Extra wide spacing preserved
++ y = 20
++ z = 30
++ return x + y + z
+*** End of File
+*** End Patch
+"""
+
+ mock_fs.apply_patch(patch)
+ content = mock_fs.read_file('boundary.py')
+
+ # Verify function_a changes
+ assert "a=10" in content
+ assert "b=20" in content
+ assert "return a*b" in content
+ assert "x=1" not in content # Only in function_a context
+
+ # Verify function_b unchanged (middle function)
+ assert "def function_b():" in content
+ assert " x = 1" in content # This should still exist in function_b
+
+ # Verify function_c changes with preserved spacing
+ assert "y = 20" in content
+ assert "z = 30" in content
+ assert "return x + y + z" in content
\ No newline at end of file