please look at this test and make sure it even makes sense how its set up:

```
@pytest.mark.asyncio
async def test_file_update_with_diff(mock_app_state, mock_file_context, monkeypatch):
    # Initial addition
    mock_app_state.conversation_history = [
        {'role': 'user', 'content': 'Create file1.txt'},
        {'role': 'assistant', 'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context."}
    ]
    mock_file_context.tracked_files["file1.txt"] = ""

    user_input = "Update file1.txt"

    # 1. Mock AI client
    ai_client_mock = AsyncMock()

    # 2. Mock the response returned by create_message with proper 'usage'
    create_message_response_mock = MagicMock(
        usage=MagicMock(
            prompt_tokens=15,
            completion_tokens=25,
            total_tokens=40,
            cache_creation_input_tokens=0,
            cache_read_input_tokens=0
        )
    )


    # 4. Set the mocked create_message to return our mocked response
    ai_client_mock.create_message.return_value = create_message_response_mock

    # 3. Mock the extract_response method on the response to return the expected string
    ai_client_mock.extract_response = AsyncMock(return_value=
        "Fresh content for /path/to/active_project/file1.txt: ```diff\n+ This is the updated content of file1\n```"
    )

    # 5. Apply monkeypatch to replace AIClientFactory.get_ai_client with our mock
    monkeypatch.setattr("chat.chat.AIClientFactory.get_ai_client", lambda x: ai_client_mock)

    # 6. Apply monkeypatch to replace get_app_state to return mock_app_state
    monkeypatch.setattr("chat.chat.get_app_state", lambda: mock_app_state)

    # 7. Apply monkeypatch to replace get_file_context to return mock_file_context
    monkeypatch.setattr("chat.chat.get_file_context", lambda: mock_file_context)

    # 8. Call the function under test
    assistant_response = await chat_with_model(user_input, MagicMock(), "gpt-4")
    
    # 9. Print internal states for debugging
    print("Conversation History:", mock_app_state.conversation_history)
    print("Tracked Files:", mock_file_context.tracked_files)
    
    # 10. Check that the conversation_history has three messages
    expected_conversation_length = 3  # Initial 2 + Assistant response
    assert len(mock_app_state.conversation_history) == expected_conversation_length, \
        f"Expected {expected_conversation_length} messages in conversation_history, found {len(mock_app_state.conversation_history)}"
    
    # 11. Check that the third message is from the assistant
    assert mock_app_state.conversation_history[2]['role'] == 'assistant', \
        f"Expected third message role to be 'assistant', got {mock_app_state.conversation_history[2]['role']}"
    
    # 12. Check the assistant response content
    expected_assistant_content = (
        "Added file1.txt to context.\nI've added `file1.txt` to the context."
        "\n### Diff for /path/to/active_project/file1.txt\n```diff\n+ This is the updated content of file1\n```"
    )
    assert mock_app_state.conversation_history[2]['content'] == expected_assistant_content, \
        f"Unexpected assistant message content: {mock_app_state.conversation_history[2]['content']}"
    
    # 13. Check that FileContextTracker was updated correctly
    assert "file1.txt" in mock_file_context.tracked_files, \
        f"Expected 'file1.txt' to be in tracked_files, got {list(mock_file_context.tracked_files.keys())}"
    
    assert mock_file_context.tracked_files["file1.txt"] == "This is the updated content of file1", \
        f"Expected tracked_files['file1.txt'] to be 'This is the updated content of file1', got '{mock_file_context.tracked_files.get('file1.txt')}'"

```

here is the error:

```
        # 10. Check that the conversation_history has three messages
        expected_conversation_length = 3  # Initial 2 + Assistant response
>       assert len(mock_app_state.conversation_history) == expected_conversation_length, \
            f"Expected {expected_conversation_length} messages in conversation_history, found {len(mock_app_state.conversation_history)}"
E       AssertionError: Expected 3 messages in conversation_history, found 4
E       assert 4 == 3
E        +  where 4 = len([{'content': 'Create file1.txt', 'role': 'user'}, {'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context.", 'role': 'assistant'}, {'content': 'Update file1.txt', 'role': 'user'}, {'content': "I've added `/path/to/active_project/file1.txt` to the context.", 'role': 'assistant'}])
E        +    where [{'content': 'Create file1.txt', 'role': 'user'}, {'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context.", 'role': 'assistant'}, {'content': 'Update file1.txt', 'role': 'user'}, {'content': "I've added `/path/to/active_project/file1.txt` to the context.", 'role': 'assistant'}] = <test_conversation_history.mock_app_state.<locals>.MockAppState object at 0x111407890>.conversation_history

tests/test_chat/test_conversation_history.py:383: AssertionError
------------------------------------------------------------- Captured stdout setup --------------------------------------------------------------
DEBUG: Using selector: KqueueSelector
--------------------------------------------------------------- Captured log setup ---------------------------------------------------------------
DEBUG    asyncio:selector_events.py:64 Using selector: KqueueSelector
-------------------------------------------------------------- Captured stdout call --------------------------------------------------------------
INFO: Processing user input: Update file1.txt
INFO: Using model: gpt-4
INFO: Available tools: []
INFO: Using AI client: AsyncMock
INFO: context awareness prompt: - **file1.txt**:
```

```

INFO: History passed to AI client: [{'role': 'user', 'content': 'Create file1.txt'}, {'role': 'assistant', 'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context."}]
INFO: Creating message with AI client
INFO: Message created successfully
INFO: EXTRACTED RESPONSE: Fresh content for /path/to/active_project/file1.txt: ```diff
+ This is the updated content of file1
```
MockFileContextTracker: Adding '/path/to/active_project/file1.txt' with content '+ This is the updated content of file1' via operation 'updated via function call'
INFO: Final assistant response: I've added `/path/to/active_project/file1.txt` to the context.
Conversation History: [{'role': 'user', 'content': 'Create file1.txt'}, {'role': 'assistant', 'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context."}, {'role': 'user', 'content': 'Update file1.txt'}, {'role': 'assistant', 'content': "I've added `/path/to/active_project/file1.txt` to the context."}]
Tracked Files: {'file1.txt': '', '/path/to/active_project/file1.txt': '+ This is the updated content of file1'}
--------------------------------------------------------------- Captured log call ----------------------------------------------------------------
INFO     root:chat.py:257 Processing user input: Update file1.txt
INFO     root:chat.py:258 Using model: gpt-4
INFO     root:chat.py:259 Available tools: []
INFO     root:chat.py:269 Using AI client: AsyncMock
INFO     root:chat.py:275 context awareness prompt: - **file1.txt**:
```

```

INFO     root:chat.py:279 History passed to AI client: [{'role': 'user', 'content': 'Create file1.txt'}, {'role': 'assistant', 'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context."}]
INFO     root:chat.py:282 Creating message with AI client
INFO     root:chat.py:289 Message created successfully
INFO     root:chat.py:319 EXTRACTED RESPONSE: Fresh content for /path/to/active_project/file1.txt: ```diff
+ This is the updated content of file1
```
INFO     root:chat.py:335 Final assistant response: I've added `/path/to/active_project/file1.txt` to the context.
------------------------------------------------------------ Captured stdout teardown ------------------------------------------------------------
DEBUG: Using selector: KqueueSelector
------------------------------------------------------------- Captured log teardown --------------------------------------------------------------
DEBUG    asyncio:selector_events.py:64 Using selector: KqueueSelector
============================================================ short test summary info =============================================================
FAILED tests/test_chat/test_conversation_history.py::test_file_update_with_diff - AssertionError: Expected 3 messages in conversation_history, found 4
assert 4 == 3
 +  where 4 = len([{'content': 'Create file1.txt', 'role': 'user'}, {'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context.", 'role': 'assistant'}, {'content': 'Update file1.txt', 'role': 'user'}, {'content': "I've added `/path/to/active_project/file1.txt` to the context.", 'role': 'assistant'}])
 +    where [{'content': 'Create file1.txt', 'role': 'user'}, {'content': "Added /path/to/active_project/file1.txt to context.\nI've added `file1.txt` to the context.", 'role': 'assistant'}, {'content': 'Update file1.txt', 'role': 'user'}, {'content': "I've added `/path/to/active_project/file1.txt` to the context.", 'role': 'assistant'}] = <test_conversation_history.mock_app_state.<locals>.MockAppState object at 0x111407890>.conversation_history
```

here is the code 

chat.py
```
import logging
import json
import os
import re
import difflib
from typing import List, Dict, Any, Tuple, Optional
from efc.efc_cache import get_file_context
from app_state import get_app_state
from chat.model_config import get_model_config
from tools.tools import ToolManager
from utils.token_usage import update_token_usage
from chat.factory import AIClientFactory
import asyncio

# Set logging level
logging.basicConfig(level=logging.INFO)


async def chat_with_model(user_input: str, tool_manager: ToolManager, model_name: str) -> str:
    logging.info(f"Processing user input: {user_input}")
    logging.info(f"Using model: {model_name}")
    logging.info(f"Available tools: {[tool['function']['name'] for tool in tool_manager.get_tool_descriptions()]}")

    app_state = get_app_state()
    # Add the new user input to the history
    app_state.conversation_history.append({"role": "user", "content": user_input})

    file_context = get_file_context()
    model_config = get_model_config(model_name)

    ai_client = AIClientFactory.get_ai_client(model_name)
    logging.info(f"Using AI client: {type(ai_client).__name__}")

    optimized_history = app_state.conversation_history[:-1]  # Exclude the latest user message

    # System message includes context awareness prompt
    file_context_summary = file_context.generate_context_awareness_prompt(app_state)
    logging.info(f"context awareness prompt: {file_context_summary}")
    system_message = f"{model_config['base_system_prompt']}\n\n{file_context_summary}"

    tools = tool_manager.get_tool_descriptions(format="claude" if model_name.lower() in ['sonnet', 'claude-3-sonnet-20240229'] else "default")
    logging.info(f"History passed to AI client: {optimized_history}")

    try:
        logging.info("Creating message with AI client")
        response = await ai_client.create_message(
            prompt=user_input,
            system_message=system_message,
            tools=tools,
            history=optimized_history
        )
        logging.info("Message created successfully")

        if hasattr(response, 'usage'):
            if model_name.lower() in ['sonnet', 'claude-3-sonnet-20240229']:
                update_token_usage(model_name, {
                    "prompt_tokens": response.usage.input_tokens,
                    "completion_tokens": response.usage.output_tokens,
                    "total_tokens": response.usage.input_tokens + response.usage.output_tokens,
                    "cache_creation_tokens": getattr(response.usage, 'cache_creation_input_tokens', 0),
                    "cache_read_tokens": getattr(response.usage, 'cache_read_input_tokens', 0)
                })
            else:
                # For Llama and GPT
                update_token_usage(model_name, {
                    "prompt_tokens": response.usage.prompt_tokens,
                    "completion_tokens": response.usage.completion_tokens,
                    "total_tokens": response.usage.total_tokens
                })
    except Exception as e:
        logging.error(f"API Error: {str(e)}")
        return f"I'm sorry, there was an error communicating with the AI. Please try again. Error: {str(e)}"

    # Extract assistant response and function calls
    if hasattr(ai_client, 'extract_response'):
        assistant_response = ai_client.extract_response(response)
        if asyncio.iscoroutine(assistant_response):
            assistant_response = await assistant_response
    else:
        assistant_response = response.content[0].text if response.content else ""

    logging.info(f"EXTRACTED RESPONSE: {assistant_response}")

    # **Process file updates and modify assistant_response accordingly**
    assistant_response = await process_file_updates(assistant_response, file_context, app_state)

    # Extract and execute function calls
    function_calls = ai_client.extract_function_calls(response)
    function_results = await execute_function_calls(function_calls, tool_manager, model_name)

    # Integrate function results into assistant response
    if not assistant_response and function_results:
        assistant_response = "I've performed the following actions based on your request:\n\n"
    assistant_response = integrate_function_results(assistant_response, function_results, model_config)

    # **Append the finalized assistant response once**
    app_state.conversation_history.append({"role": "assistant", "content": assistant_response})
    logging.info(f"Final assistant response: {assistant_response}")
    return assistant_response


async def process_file_updates(assistant_response: str, file_context, app_state: Any) -> str:
    updated_files = detect_file_updates(assistant_response)
    notifications = []

    for relative_path, new_content in updated_files.items():
        existing_content = file_context.get_file_content(relative_path)

        if new_content is not None:
            if existing_content:
                # Existing file: calculate diff
                diff = calculate_diff(existing_content, new_content)
                if diff.strip():
                    # Include diff in the assistant response
                    diff_message = f"\n### Diff for {relative_path}\n```diff\n{diff}\n```"
                    assistant_response += diff_message
                else:
                    # No changes detected
                    no_change_msg = f"\nNo changes detected in {relative_path}."
                    assistant_response += no_change_msg
            else:
                # First instance: notification about addition
                notification_message = f"\nI've added `{relative_path}` to the context."
                assistant_response += notification_message

            # Update the FileContextTracker with new content
            file_context.add_or_update_file(relative_path, new_content, "updated via function call")

            # Optionally, remove the processed content from assistant_response
            assistant_response = remove_full_content_from_response(assistant_response, relative_path)
        else:
            # Handle additions where no new content is provided
            notification_message = f"\nI've added `{relative_path}` to the context."
            assistant_response += notification_message

            # Update the FileContextTracker to reflect the addition
            file_context.add_or_update_file(relative_path, "", "added via function call")

    return assistant_response.strip()


def detect_file_updates(assistant_message: str) -> Dict[str, Optional[str]]:
    """
    Detects and extracts file updates from the assistant message.
    Returns a dictionary mapping relative_path to new_content or None for additions.
    """
    # Pattern for file updates: "Fresh content for {relative_path}: ```(diff|language)?\n...```"
    pattern = r"Fresh content for (?P<path>[^\n]+):\s*```(?:[^\n]*)\n(?P<content>[\s\S]*?)```"
    matches = re.finditer(pattern, assistant_message)
    updates = {}
    for match in matches:
        relative_path = match.group('path').strip()
        content = match.group('content').strip()
        updates[relative_path] = content

    # Pattern for additions: "Added {relative_path} to context."
    pattern_added = r"Added (?P<path>[^\n]+) to context\."
    matches_added = re.finditer(pattern_added, assistant_message)
    for match in matches_added:
        relative_path = match.group('path').strip()
        updates[relative_path] = None  # None content for additions

    return updates


def calculate_diff(old_content: str, new_content: str) -> str:
    old_lines = old_content.splitlines()
    new_lines = new_content.splitlines()
    diff = difflib.unified_diff(old_lines, new_lines, lineterm='')
    return '\n'.join(diff)


def remove_full_content_from_response(assistant_message: str, relative_path: str) -> str:
    """
    Removes the full file content from the assistant message, leaving only the relevant response.
    """
    # Pattern captures any leading whitespace before 'Fresh content...' as well
    pattern = rf"\s*Fresh content for {re.escape(relative_path)}:.*?```.*?\n[\s\S]*?```"
    cleaned_message = re.sub(pattern, "", assistant_message, flags=re.MULTILINE)
    # Replace multiple spaces with a single space and strip leading/trailing spaces
    cleaned_message = re.sub(r'\s{2,}', ' ', cleaned_message).strip()
    return cleaned_message


async def execute_function_calls(function_calls, tool_manager: ToolManager, model_name: str):
    results = []
    if asyncio.iscoroutine(function_calls):
        function_calls = await function_calls
    for function_call in function_calls:
        try:
            if isinstance(function_call, dict):
                # Llama format
                func_name = function_call.get('function')
                arguments = function_call.get('arguments', {})
            else:
                # GPT-4 format
                func_name = function_call.function.name
                arguments = json.loads(function_call.function.arguments)

            result = await tool_manager.execute_tool({"function": func_name, "arguments": arguments}, model_name)
            results.append((func_name, arguments, result))
        except Exception as e:
            logging.error(f"Error executing function: {str(e)}")
            results.append((func_name, arguments, f"Error executing function: {str(e)}"))
    return results


def integrate_function_results(assistant_response: str, function_results: List[Tuple[str, Dict, str]], model_config: Dict) -> str:
    if not assistant_response and function_results:
        assistant_response = "I've performed the following actions based on your request:\n\n"

    for func_name, args, result in function_results:
        if model_config.get('use_tool_calls', False):
            assistant_response += f"\n\nResult of {func_name}: {result}"
        else:
            # For models that embed function calls in the response
            placeholder = f"<function={func_name}>{json.dumps(args)}</function>"
            if placeholder in assistant_response:
                assistant_response = assistant_response.replace(placeholder, str(result))
            else:
                assistant_response += f"\n\nResult of {func_name}: {result}"

    return assistant_response

```