/ archive / python / kamaji / file_context.py
file_context.py
  1  """
  2  File context management for Kamagi.
  3  Allows reading and including files in conversation context.
  4  """
  5  
  6  from pathlib import Path
  7  from typing import List, Dict, Optional
  8  
  9  
 10  def read_file_content(file_path: str) -> Optional[str]:
 11      """
 12      Read content from a file.
 13  
 14      Args:
 15          file_path: Path to the file to read
 16  
 17      Returns:
 18          File content or None if error
 19      """
 20      try:
 21          path = Path(file_path)
 22          if not path.exists():
 23              return None
 24          if not path.is_file():
 25              return None
 26  
 27          # Read with UTF-8, fallback to latin-1 for binary-ish files
 28          try:
 29              with open(path, 'r', encoding='utf-8') as f:
 30                  return f.read()
 31          except UnicodeDecodeError:
 32              with open(path, 'r', encoding='latin-1') as f:
 33                  return f.read()
 34      except Exception:
 35          return None
 36  
 37  
 38  def load_files(file_paths: List[str]) -> Dict[str, str]:
 39      """
 40      Load multiple files and return their contents.
 41  
 42      Args:
 43          file_paths: List of file paths to load
 44  
 45      Returns:
 46          Dictionary mapping file paths to their contents
 47      """
 48      files = {}
 49      for file_path in file_paths:
 50          content = read_file_content(file_path)
 51          if content is not None:
 52              files[file_path] = content
 53      return files
 54  
 55  
 56  def format_file_context(files: Dict[str, str]) -> str:
 57      """
 58      Format file contents for inclusion in conversation context.
 59  
 60      Args:
 61          files: Dictionary of file paths and contents
 62  
 63      Returns:
 64          Formatted context string
 65      """
 66      if not files:
 67          return ""
 68  
 69      context_parts = ["Here are the files you have access to:\n"]
 70  
 71      for file_path, content in files.items():
 72          # Truncate very long files
 73          max_length = 10000
 74          if len(content) > max_length:
 75              content = content[:max_length] + f"\n\n[... truncated, file is {len(content)} characters total]"
 76  
 77          context_parts.append(f"\n--- {file_path} ---")
 78          context_parts.append(content)
 79          context_parts.append("--- End of file ---\n")
 80  
 81      return "\n".join(context_parts)
 82  
 83  
 84  def create_context_prompt(user_message: str, file_context: str) -> str:
 85      """
 86      Create a prompt that includes both user message and file context.
 87  
 88      Args:
 89          user_message: The user's message
 90          file_context: Formatted file context
 91  
 92      Returns:
 93          Combined prompt
 94      """
 95      if not file_context:
 96          return user_message
 97  
 98      return f"""{file_context}
 99  
100  Based on the files above, please respond to this request:
101  
102  {user_message}"""