Capítulo 8 — Búsqueda por rutas de archivo
Commit:
43f213a— Add support for searching in file paths (birbbit/Hristijan Bogoevski, 10 febrero 2024)
¿Qué se construyó?
Este es el PR más grande del proyecto de la comunidad. Hristijan Bogoevski (birbbit) agregó soporte para buscar en una lista específica de archivos en lugar de un directorio completo.
También refactorizó el código para separar responsabilidades en funciones más pequeñas.
El nuevo parámetro file_paths
# ANTES: solo podías buscar en un directorio
search("función de pagos", path="./src")
# AHORA: también en una lista específica de archivos
search("función de pagos", file_paths=["./src/payments.py", "./src/orders.py"])Esto es crucial para Open Interpreter: el agente puede seleccionar los archivos más relevantes del proyecto y pedirle a aifs que busque solo en esos.
La lógica de decidir dónde guardar el índice
def search(query, path=None, file_paths=None, max_results=5, ...):
if path is None:
# Mode: lista de archivos específicos
common_prefix = os.path.commonprefix(file_paths)
if not common_prefix.endswith("/"):
common_prefix = os.path.dirname(common_prefix)
path_to_index = os.path.join(common_prefix, "_.aifs")
else:
# Mode: directorio completo
path_to_index = os.path.join(path, "_.aifs")Cuando se usa file_paths, el índice se guarda en el directorio más cercano común a todos los archivos.
Ejemplo:
file_paths = [
"/proyecto/src/payments.py",
"/proyecto/src/orders.py",
"/proyecto/tests/test_payments.py"
]
common_prefix = "/proyecto" # el prefijo común
path_to_index = "/proyecto/_.aifs"La nueva función index_files()
def index_files(file_paths, existingIndex=None, indexPath="", python_docstrings_only=False):
if existingIndex is None:
existingIndex = {}
index = existingIndex
deletedFiles = handle_deleted_files(index)
modifiedFiles = handle_modified_files(index, python_docstrings_only)
writeToIndex = len(deletedFiles) > 0 or len(modifiedFiles) > 0
for file_path in file_paths:
if file_path not in index or file_path in modifiedFiles:
file_index = index_file(file_path, python_docstrings_only)
if file_index:
index[file_path] = file_index
save_index(writeToIndex, index, indexPath)
return indexLa diferencia con index_directory(): en lugar de hacer os.walk() para descubrir archivos, itera sobre la lista explícita.
Refactoring: funciones más pequeñas
birbbit también extrajo funciones helper:
def handle_deleted_files(index: dict) -> List[str]:
"""updates the index to remove deleted files. returns deleted files"""
deletedFiles = []
for file_path, _ in index.items():
if not os.path.isfile(file_path):
deletedFiles.append(file_path)
for file_path in deletedFiles:
index.pop(file_path, None)
return deletedFiles
def handle_modified_files(index: dict, python_docstrings_only: bool) -> List[str]:
modifiedFiles = []
for file_path, file_index in index.items():
if os.path.getmtime(file_path) != file_index["last_modified"]:
new_file_index = index_file(file_path, python_docstrings_only)
index[file_path] = new_file_index
modifiedFiles.append(file_path)
return modifiedFiles
def save_index(writeToIndex, index, indexPath):
if writeToIndex:
with open(indexPath, "w") as f:
json.dump(index, f)Estas funciones se reutilizan tanto en index_files() como en index_directory().
Un bug que se coló
# BUG: usa 'and' en lugar de 'or' — nunca excluye nada
if file_path.endswith("_index.aifs") and file_path.endswith(".DS_Store") and file_path.endswith("_.aifs"):
continue
# CORRECCIÓN esperada:
if file_path.endswith("_index.aifs") or file_path.endswith(".DS_Store") or file_path.endswith("_.aifs"):
continueUn archivo no puede terminar en _index.aifs Y .DS_Store al mismo tiempo, así que la condición nunca se cumple. Los archivos de índice se terminan incluyendo en la búsqueda. Este bug no fue detectado en este commit.
Lección del capítulo
La API de una librería debe crecer con los casos de uso reales de sus usuarios. El parámetro
file_pathssurgió de una necesidad concreta: Open Interpreter necesitaba buscar en archivos específicos, no en directorios completos.
Siguiente: Cap 09 — Contribuciones de la comunidad