Hello we are going to work on a feature/refactor for my program first i will give you some code context that will help you understand my thinking and feature request. Then we will do a comprehension check and refactor my query for clarity so we are calibrated. Then in a final query we will do the actual implementation and make sure there are no regressions. First here is the code and the initial query: study this and pay close attention to how conversation history is currently used to store file context. This will be the key change we will make.

chat.py
```
import logging
import json
import os
from typing import List, Dict, Any, Tuple
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
import logging
# logging.basicConfig(level=logging.DEBUG)


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 before optimization
    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 = optimize_conversation_history(app_state.conversation_history, app_state.file_histories)
    # file_context_summary = file_context.get_context_for_llm()
    file_context_summary =  file_context.generate_context_awareness_prompt(app_state)
    logging.info(f"context awareness promptt: {file_context_summary}")
    # system_message = f"{model_config['base_system_prompt']}\n\n{model_config['function_definitions']}\n\n{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[:-1]
        )
        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)}"

        # With:
    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}")
    function_calls = ai_client.extract_function_calls(response)
    function_results = await execute_function_calls(function_calls, tool_manager, model_name)
    
    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)


    app_state.conversation_history.append({"role": "assistant", "content": assistant_response})
    logging.info(f"Final assistant response: {assistant_response}")
    return assistant_response


async def execute_function_calls(function_calls, tool_manager, model_name):
    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:
        assistant_response = "Here are the results of the actions I've taken:\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


from dataclasses import dataclass
from typing import List, Dict, Any
import difflib
import logging
import time

@dataclass
class FileHistory:
    most_recent_content: str
    second_most_recent_content: str
    diff_summary: str
    last_update_timestamp: float


def optimize_conversation_history(history: List[Dict[str, Any]], file_histories: Dict[str, FileHistory]) -> List[Dict[str, Any]]:
    # logging.info(f"History before optimization: {history}")
    optimized_history = history.copy()
    file_instance_count = {}
    file_instances = {}

    # First pass: count instances and collect content
    for i, message in enumerate(optimized_history):
        if message['role'] == 'assistant' and is_file_content(message['content']):
            relative_path = extract_relative_path(message['content'])
            file_instance_count[relative_path] = file_instance_count.get(relative_path, 0) + 1
            if relative_path not in file_instances:
                file_instances[relative_path] = []
            file_content = extract_file_content(message['content'])
            file_instances[relative_path].append((i, file_content))
            
            # Update the message content with relative path
            message['content'] = f"Fresh content for {relative_path}: {file_content}"

    # Second pass: summarize oldest instance if more than two
    for relative_path, instances in file_instances.items():
        if len(instances) > 2:
            oldest_index, oldest_content = instances[0]
            second_oldest_index, second_oldest_content = instances[1]
            newest_index, newest_content = instances[-1]

            if file_histories is not None:
                update_file_history(relative_path, newest_content, file_histories, is_latest=True)
                update_file_history(relative_path, second_oldest_content, file_histories, is_latest=False)

            summary = generate_summary(relative_path, oldest_content, newest_content, second_oldest_content)
            optimized_history[oldest_index]['content'] = summary
    logging.info(f"History after optimization: {optimized_history}")
    return optimized_history

def extract_relative_path(content: str) -> str:
    app_state = get_app_state()
    active_project = app_state.active_project
    if "Fresh content for" in content:
        full_path = content.split("Fresh content for")[1].split(":")[0].strip()
    elif "Cached content for" in content:
        full_path = content.split("Cached content for")[1].split(":")[0].strip()
    else:
        return "Unknown File"
    
    return os.path.relpath(full_path, active_project)

def generate_summary(relative_path: str, original_content: str, latest_content: str, second_latest_content: str, max_length: int = 200) -> str:
    app_state = get_app_state()
    active_project = os.path.basename(app_state.active_project)

    original_lines = original_content.splitlines()
    latest_lines = latest_content.splitlines()
    second_latest_lines = second_latest_content.splitlines()

    diff1 = list(difflib.unified_diff(original_lines, second_latest_lines, lineterm=''))
    diff2 = list(difflib.unified_diff(second_latest_lines, latest_lines, lineterm=''))

    changes1 = [line for line in diff1 if line.startswith('+') or line.startswith('-')][:3]
    changes2 = [line for line in diff2 if line.startswith('+') or line.startswith('-')][:3]

    summary = f"Original content: {original_content[:50]}... "
    if changes1:
        summary += f"First update changes: {'; '.join(changes1)} "
    if changes2:
        summary += f"Second update changes: {'; '.join(changes2)}"

    return f"Summary of changes in {relative_path} (in project: {active_project}, as of {time.strftime('%Y-%m-%d %H:%M:%S')}): {summary[:max_length]}..."

def update_file_history(relative_path: str, new_content: str, file_histories: Dict[str, FileHistory], is_latest: bool) -> None:
    if relative_path not in file_histories:
        file_histories[relative_path] = FileHistory(new_content, "", "", time.time())
    else:
        history = file_histories[relative_path]
        if is_latest:
            history.second_most_recent_content = history.most_recent_content
            history.most_recent_content = new_content
        else:
            history.second_most_recent_content = new_content
        history.last_update_timestamp = time.time()

def is_file_content(content: str) -> bool:
    return "Fresh content for" in content or "Cached content for" in content

def extract_file_content(content: str) -> str:
    return content.split(":", 1)[1].strip()
```
efc_cache.py
```
import time
from typing import Dict, Any, Optional
from datetime import datetime
import hashlib
import logging
import os
import time
import hashlib
from datetime import datetime
from typing import Dict, Any, Optional
from app_state import get_app_state

class FileCache:
    def __init__(self):
        self._cache: Dict[str, Dict[str, Any]] = {}

    def get(self, relative_path: str) -> Optional[str]:
        if relative_path in self._cache:
            cache_entry = self._cache[relative_path]
            if time.time() - cache_entry['timestamp'] < 3000:  # 50 minutes expiration
                return cache_entry['content']
        return None

    def set(self, relative_path: str, content: str) -> None:
        self._cache[relative_path] = {
            'content': content,
            'timestamp': time.time()
        }

    def clear(self, relative_path: Optional[str] = None) -> None:
        if relative_path:
            self._cache.pop(relative_path, None)
        else:
            self._cache.clear()

class FileContextTracker:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(FileContextTracker, cls).__new__(cls)
            cls._instance.tracked_files = {}
            cls._instance.last_api_call_time = datetime.min
            cls._instance.file_cache = FileCache()
        return cls._instance

    def force_refresh(self):
        app_state = get_app_state()
        project_root = app_state.active_project
        for relative_path in list(self.tracked_files.keys()):
            try:
                full_path = os.path.join(project_root, relative_path)
                with open(full_path, 'r') as f:
                    content = f.read()
                content_hash = self._hash_content(content)
                
                cached_content = self.file_cache.get(relative_path)
                if cached_content and self._hash_content(cached_content) == content_hash:
                    self.tracked_files[relative_path]["last_checked"] = datetime.now()
                else:
                    self.add_or_update_file(relative_path, content, "refresh")
            except FileNotFoundError:
                del self.tracked_files[relative_path]
                self.file_cache.clear(relative_path)
            except Exception as e:
                logging.error(f"Error refreshing file {relative_path}: {str(e)}")

    def add_or_update_file(self, relative_path: str, content: str, operation: str) -> str:
        current_time = datetime.now()
        content_hash = self._hash_content(content)

        self.file_cache.set(relative_path, content)

        if relative_path in self.tracked_files:
            if self.tracked_files[relative_path]["content_hash"] == content_hash:
                self.tracked_files[relative_path]["last_checked"] = current_time
                return f"File {relative_path} unchanged, no update needed."
            
            self.tracked_files[relative_path].update({
                "last_operation": f"updated ({operation})",
                "last_updated": current_time,
                "content_hash": content_hash,
            })
            message = f"Updated {relative_path} in context due to content change."
        else:
            self.tracked_files[relative_path] = {
                "last_operation": operation,
                "last_updated": current_time,
                "content_hash": content_hash,
                "created_at": current_time
            }
            message = f"Added {relative_path} to context."

        return message

    def get_file_content(self, relative_path: str) -> Optional[str]:
        return self.file_cache.get(relative_path)

    def _get_context_for_llm(self) -> str:
        if not self.tracked_files:
            return "No files in context"
        context = ""
        for relative_path, info in self.tracked_files.items():
            context += f"- {relative_path} (Last {info['last_operation']} at {info['last_updated']})\n"
        return context

    def get_context_for_user(self) -> str:
        self.force_refresh()
        summary = "Files in context:\n"
        for relative_path, info in self.tracked_files.items():
            summary += f"- {relative_path} (Last {info['last_operation']} at {info['last_updated']})\n"
        return summary

    def get_full_context(self) -> Dict[str, Any]:
        return {
            "tracked_files": self.tracked_files,
            "file_contents": {path: self.get_file_content(path) for path in self.tracked_files}
        }

    @staticmethod
    def _hash_content(content: str) -> str:
        return hashlib.md5(content.encode()).hexdigest()
    


    def generate_context_awareness_prompt(self, app_state) -> str:
        """Generates the prompt section for contextual awareness, including the active project structure."""

        project_tree = app_state.get_active_project_tree_string()

        context_prompt = f"""
            ## Contextual Awareness:  IMPORTANT

            ARC, before executing any function, **always check if the information you need is already available in your current context.**  This will enhance your efficiency and demonstrate a deeper understanding of the project.

            For example, if the file content or project structure you require has already been provided, use that information directly instead of making unnecessary function calls. 

            **Active Project Structure:**
            {project_tree}

            **Files in context:**
            {self._get_context_for_llm()}

            When working with files, always use relative paths based on the active project structure shown above.
        """

        return context_prompt
    
def get_file_context():
    return FileContextTracker()
```
app_state.py
```
import os

class AppState:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(AppState, cls).__new__(cls)
            cls._instance.conversation_history = []
            cls._instance.file_histories = {}
            cls._instance.file_contents = {}
            cls._instance.code_editor_memory = []
            cls._instance.code_editor_files = set()
            cls._instance.running_processes = {}
            cls._instance.automode = False
            cls._instance.edit_history = []
            cls._instance.raw_output_mode = False
            cls._instance.token_usage = {
                "main_model": {"input": 0, "output": 0, "cost": 0},
                "tool_usage": {"input": 0, "output": 0, "cost": 0}
            }
            cls._instance.active_project = None
            cls._instance.current_turn_total_tokens: int = 0
            cls._instance.active_project_tree = {}  # New attribute for storing the active project's tree structure
            
        return cls._instance

    def update_active_project_tree(self):
        """
        Update the tree structure of the active project.
        """
        if not self.active_project:
            self.active_project_tree = {}
            return

        self.active_project_tree = self._generate_tree_structure(self.active_project)

    def _generate_tree_structure(self, path):
        """
        Generate a tree structure of the given path.
        """
        tree = {}
        for item in os.listdir(path):
            item_path = os.path.join(path, item)
            if os.path.isdir(item_path):
                tree[item] = self._generate_tree_structure(item_path)
            else:
                tree[item] = "file"
        return tree

    def get_active_project_tree_string(self):
        """
        Get a string representation of the active project's tree structure.
        """
        if not self.active_project or not self.active_project_tree:
            return "No active project"

        def _tree_to_string(tree, indent=""):
            result = ""
            for i, (name, value) in enumerate(tree.items()):
                if i == len(tree) - 1:
                    result += f"{indent}└── {name}\n"
                    if isinstance(value, dict):
                        result += _tree_to_string(value, indent + "    ")
                else:
                    result += f"{indent}├── {name}\n"
                    if isinstance(value, dict):
                        result += _tree_to_string(value, indent + "│   ")
            return result

        project_name = os.path.basename(self.active_project)
        project_name_width = len("Active Project: ") + len(project_name)
        indent = " " * project_name_width
        return f"Active Project: {project_name}\n" + _tree_to_string(self.active_project_tree, indent=indent)

def get_app_state():
    return AppState()
```