diff --git a/ra_aid/__main__.py b/ra_aid/__main__.py
index 6069cf0..64f1605 100644
--- a/ra_aid/__main__.py
+++ b/ra_aid/__main__.py
@@ -63,6 +63,8 @@ from ra_aid.database.repositories.config_repository import (
ConfigRepositoryManager,
get_config_repository
)
+from ra_aid.env_inv import EnvDiscovery
+from ra_aid.env_inv_context import EnvInvManager, get_env_inv
from ra_aid.model_formatters import format_key_facts_dict
from ra_aid.model_formatters.key_snippets_formatter import format_key_snippets_dict
from ra_aid.console.output import cpm
@@ -506,13 +508,19 @@ def main():
config = {}
# Initialize repositories with database connection
+ # Create environment inventory data
+ env_discovery = EnvDiscovery()
+ env_discovery.discover()
+ env_data = env_discovery.format_markdown()
+
with KeyFactRepositoryManager(db) as key_fact_repo, \
KeySnippetRepositoryManager(db) as key_snippet_repo, \
HumanInputRepositoryManager(db) as human_input_repo, \
ResearchNoteRepositoryManager(db) as research_note_repo, \
RelatedFilesRepositoryManager() as related_files_repo, \
WorkLogRepositoryManager() as work_log_repo, \
- ConfigRepositoryManager(config) as config_repo:
+ ConfigRepositoryManager(config) as config_repo, \
+ EnvInvManager(env_data) as env_inv:
# This initializes all repositories and makes them available via their respective get methods
logger.debug("Initialized KeyFactRepository")
logger.debug("Initialized KeySnippetRepository")
@@ -521,6 +529,7 @@ def main():
logger.debug("Initialized RelatedFilesRepository")
logger.debug("Initialized WorkLogRepository")
logger.debug("Initialized ConfigRepository")
+ logger.debug("Initialized Environment Inventory")
# Check dependencies before proceeding
check_dependencies()
@@ -671,6 +680,7 @@ def main():
key_facts=format_key_facts_dict(get_key_fact_repository().get_facts_dict()),
key_snippets=format_key_snippets_dict(get_key_snippet_repository().get_snippets_dict()),
project_info=formatted_project_info,
+ env_inv=get_env_inv(),
),
config,
)
@@ -763,4 +773,4 @@ def main():
sys.exit(0)
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff --git a/ra_aid/agent_utils.py b/ra_aid/agent_utils.py
index 7cf2ef1..1fd3daa 100644
--- a/ra_aid/agent_utils.py
+++ b/ra_aid/agent_utils.py
@@ -98,6 +98,7 @@ from ra_aid.tools.memory import (
log_work_event,
)
from ra_aid.database.repositories.config_repository import get_config_repository
+from ra_aid.env_inv_context import get_env_inv
console = Console()
@@ -422,6 +423,8 @@ def run_research_agent(
logger.warning(f"Failed to get project info: {e}")
formatted_project_info = ""
+ # Get environment inventory information
+
prompt = (RESEARCH_ONLY_PROMPT if research_only else RESEARCH_PROMPT).format(
current_date=current_date,
working_directory=working_directory,
@@ -440,6 +443,7 @@ def run_research_agent(
related_files=related_files,
project_info=formatted_project_info,
new_project_hints=NEW_PROJECT_HINTS if project_info.is_new else "",
+ env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@@ -562,6 +566,8 @@ def run_web_research_agent(
current_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
working_directory = os.getcwd()
+ # Get environment inventory information
+
prompt = WEB_RESEARCH_PROMPT.format(
current_date=current_date,
working_directory=working_directory,
@@ -572,6 +578,7 @@ def run_web_research_agent(
work_log=get_work_log_repository().format_work_log(),
key_snippets=key_snippets,
related_files=related_files,
+ env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@@ -688,6 +695,8 @@ def run_planning_agent(
logger.error(f"Failed to access research note repository: {str(e)}")
formatted_research_notes = ""
+ # Get environment inventory information
+
planning_prompt = PLANNING_PROMPT.format(
current_date=current_date,
working_directory=working_directory,
@@ -706,6 +715,7 @@ def run_planning_agent(
if config.get("research_only")
else " Only request implementation if the user explicitly asked for changes to be made."
),
+ env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@@ -808,6 +818,8 @@ def run_task_implementation_agent(
logger.error(f"Failed to access research note repository: {str(e)}")
formatted_research_notes = ""
+ # Get environment inventory information
+
prompt = IMPLEMENTATION_PROMPT.format(
current_date=current_date,
working_directory=working_directory,
@@ -831,6 +843,7 @@ def run_task_implementation_agent(
if config.get("web_research_enabled")
else ""
),
+ env_inv=get_env_inv(),
)
config = get_config_repository().get_all() if not config else config
@@ -991,78 +1004,6 @@ def _handle_fallback_response(
msg_list.extend(msg_list_response)
-# def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
-# for chunk in agent.stream({"messages": msg_list}, config):
-# logger.debug("Agent output: %s", chunk)
-# check_interrupt()
-# agent_type = get_agent_type(agent)
-# print_agent_output(chunk, agent_type)
-# if is_completed() or should_exit():
-# reset_completion_flags()
-# break
-# def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
-# while True: ## WE NEED TO ONLY KEEP ITERATING IF IT IS AN INTERRUPT, NOT UNCONDITIONALLY
-# stream = agent.stream({"messages": msg_list}, config)
-# for chunk in stream:
-# logger.debug("Agent output: %s", chunk)
-# check_interrupt()
-# agent_type = get_agent_type(agent)
-# print_agent_output(chunk, agent_type)
-# if is_completed() or should_exit():
-# reset_completion_flags()
-# return True
-# print("HERE!")
-
-# def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
-# while True:
-# for chunk in agent.stream({"messages": msg_list}, config):
-# print("Chunk received:", chunk)
-# check_interrupt()
-# agent_type = get_agent_type(agent)
-# print_agent_output(chunk, agent_type)
-# if is_completed() or should_exit():
-# reset_completion_flags()
-# return True
-# print("HERE!")
-# print("Config passed to _run_agent_stream:", config)
-# print("Config keys:", list(config.keys()))
-
-# # Ensure the configuration for state retrieval contains a 'configurable' key.
-# state_config = config.copy()
-# if "configurable" not in state_config:
-# print("Key 'configurable' not found in config. Adding it as an empty dict.")
-# state_config["configurable"] = {}
-# print("Using state_config for agent.get_state():", state_config)
-
-# try:
-# state = agent.get_state(state_config)
-# print("Agent state retrieved:", state)
-# print("State type:", type(state))
-# print("State attributes:", dir(state))
-# except Exception as e:
-# print("Error retrieving agent state with state_config", state_config, ":", e)
-# raise
-
-# # Since state.current is not available, we rely solely on state.next.
-# try:
-# next_node = state.next
-# print("State next value:", next_node)
-# except Exception as e:
-# print("Error accessing state.next:", e)
-# next_node = None
-
-# # Resume execution if state.next is truthy (indicating further steps remain).
-# if next_node:
-# print("Resuming execution because state.next is nonempty:", next_node)
-# agent.invoke(None, config)
-# continue
-# else:
-# print("No further steps indicated; breaking out of loop.")
-# break
-
-# return True
-
-
def _run_agent_stream(agent: RAgents, msg_list: list[BaseMessage], config: dict):
"""
Streams agent output while handling completion and interruption.
@@ -1205,4 +1146,4 @@ def run_agent_with_retry(
_handle_api_error(e, attempt, max_retries, base_delay)
finally:
- _restore_interrupt_handling(original_handler)
\ No newline at end of file
+ _restore_interrupt_handling(original_handler)
diff --git a/ra_aid/env_inv_context.py b/ra_aid/env_inv_context.py
new file mode 100644
index 0000000..3462148
--- /dev/null
+++ b/ra_aid/env_inv_context.py
@@ -0,0 +1,92 @@
+"""
+Context management for environment inventory.
+
+This module provides thread-safe access to environment inventory information
+using context variables.
+"""
+
+import contextvars
+from typing import Dict, Any, Optional, Type
+
+# Create contextvar to hold the environment inventory
+env_inv_var = contextvars.ContextVar("env_inv", default=None)
+
+
+class EnvInvManager:
+ """
+ Context manager for environment inventory.
+
+ This class provides a context manager interface for environment inventory,
+ using the contextvars approach for thread safety.
+
+ Example:
+ from ra_aid.env_inv import EnvDiscovery
+
+ # Get environment inventory
+ env_discovery = EnvDiscovery()
+ env_discovery.discover()
+ env_data = env_discovery.format_markdown()
+
+ # Set as current environment inventory
+ with EnvInvManager(env_data) as env_mgr:
+ # Environment inventory is now available through get_env_inv()
+ pass
+ """
+
+ def __init__(self, env_data: Dict[str, Any]):
+ """
+ Initialize the EnvInvManager.
+
+ Args:
+ env_data: Dictionary containing environment inventory data
+ """
+ self.env_data = env_data
+
+ def __enter__(self) -> 'EnvInvManager':
+ """
+ Set the environment inventory and return self.
+
+ Returns:
+ EnvInvManager: The initialized manager
+ """
+ env_inv_var.set(self.env_data)
+ return self
+
+ def __exit__(
+ self,
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[object],
+ ) -> None:
+ """
+ Reset the environment inventory when exiting the context.
+
+ Args:
+ exc_type: The exception type if an exception was raised
+ exc_val: The exception value if an exception was raised
+ exc_tb: The traceback if an exception was raised
+ """
+ # Reset the contextvar to None
+ env_inv_var.set(None)
+
+ # Don't suppress exceptions
+ return False
+
+
+def get_env_inv() -> Dict[str, Any]:
+ """
+ Get the current environment inventory.
+
+ Returns:
+ Dict[str, Any]: The current environment inventory
+
+ Raises:
+ RuntimeError: If no environment inventory has been initialized with EnvInvManager
+ """
+ env_data = env_inv_var.get()
+ if env_data is None:
+ raise RuntimeError(
+ "No environment inventory available. "
+ "Make sure to initialize one with EnvInvManager first."
+ )
+ return env_data
diff --git a/ra_aid/prompts/chat_prompts.py b/ra_aid/prompts/chat_prompts.py
index a914b5a..d1bbf54 100644
--- a/ra_aid/prompts/chat_prompts.py
+++ b/ra_aid/prompts/chat_prompts.py
@@ -23,6 +23,9 @@ Current Date: {current_date}
Project Info:
{project_info}
+Environment Info:
+{env_inv}
+
Agentic Chat Mode Instructions:
Overview:
diff --git a/ra_aid/prompts/implementation_prompts.py b/ra_aid/prompts/implementation_prompts.py
index 4f0b20d..6c10b9e 100644
--- a/ra_aid/prompts/implementation_prompts.py
+++ b/ra_aid/prompts/implementation_prompts.py
@@ -29,6 +29,16 @@ Working Directory: {working_directory}
{research_notes}
+
+{env_inv}
+
+
+MAKE USE OF THE ENVIRONMENT INVENTRY TO GET YOUR WORK DONE AS EFFICIENTLY AND ACCURATELY AS POSSIBLE
+
+E.G. IF WE ARE USING A LIBRARY AND IT IS FOUND IN ENV INVENTORY, ADD THE INCLUDE/LINKER FLAGS TO YOUR MAKEFILE/CMAKELISTS/COMPILATION COMMAND/ETC.
+
+YOU MUST **EXPLICITLY** INCLUDE ANY PATHS FROM THE ABOVE INFO IF NEEDED. IT IS NOT AUTOMATIC.
+
Important Notes:
- Focus solely on the given task and implement it as described.
- Scale the complexity of your solution to the complexity of the request. For simple requests, keep it straightforward and minimal. For complex requests, maintain the previously planned depth.
@@ -75,4 +85,4 @@ FOLLOW TEST DRIVEN DEVELOPMENT (TDD) PRACTICES WHERE POSSIBE. E.G. COMPILE CODE
IF YOU CAN SEE THE CODE WRITTEN/CHANGED BY THE PROGRAMMER, TRUST IT. YOU DO NOT NEED TO RE-READ EVERY FILE WITH EVERY SMALL EDIT.
NEVER ANNOUNCE WHAT YOU ARE DOING, JUST DO IT!
-"""
\ No newline at end of file
+"""
diff --git a/ra_aid/prompts/planning_prompts.py b/ra_aid/prompts/planning_prompts.py
index ecb18e6..c82a13f 100644
--- a/ra_aid/prompts/planning_prompts.py
+++ b/ra_aid/prompts/planning_prompts.py
@@ -11,30 +11,37 @@ from ra_aid.prompts.web_research_prompts import WEB_RESEARCH_PROMPT_SECTION_PLAN
PLANNING_PROMPT = """Current Date: {current_date}
Working Directory: {working_directory}
-
-{base_task}
-
-
KEEP IT SIMPLE
-Project Info:
+
{project_info}
+
-Research Notes:
-
+
{research_notes}
-
+
-Relevant Files:
-{related_files}
-
-Key Facts:
+
{key_facts}
+
-Key Snippets:
+
{key_snippets}
+
+
+
+{env_inv}
+
+
+MAKE USE OF THE ENVIRONMENT INVENTRY TO GET YOUR WORK DONE AS EFFICIENTLY AND ACCURATELY AS POSSIBLE
+
+E.G. IF WE ARE USING A LIBRARY AND IT IS FOUND IN ENV INVENTORY, ADD THE INCLUDE/LINKER FLAGS TO YOUR MAKEFILE/CMAKELISTS/COMPILATION COMMAND/
+ETC.
+
+YOU MUST **EXPLICITLY** INCLUDE ANY PATHS FROM THE ABOVE INFO IF NEEDED. IT IS NOT AUTOMATIC.
Work done so far:
+
{work_log}
@@ -78,6 +85,12 @@ You have often been criticized for:
- Asking the user if they want to implement the plan (you are an *autonomous* agent, with no user interaction unless you use the ask_human tool explicitly).
- Not calling tools/functions properly, e.g. leaving off required arguments, calling a tool in a loop, calling tools inappropriately.
+
+{base_task}
+
+
+YOU MUST FOCUS ON THIS BASE TASK. IT TAKES PRECEDENT OVER EVERYTHING ELSE.
+
DO NOT WRITE ANY FILES YET. CODE WILL BE WRITTEN AS YOU CALL request_task_implementation.
DO NOT USE run_shell_command TO WRITE ANY FILE CONTENTS! USE request_task_implementation.
@@ -85,4 +98,4 @@ DO NOT USE run_shell_command TO WRITE ANY FILE CONTENTS! USE request_task_implem
WORK AND TEST INCREMENTALLY, AND RUN MULTIPLE IMPLEMENTATION TASKS WHERE APPROPRIATE.
NEVER ANNOUNCE WHAT YOU ARE DOING, JUST DO IT!
-"""
\ No newline at end of file
+"""
diff --git a/ra_aid/prompts/research_prompts.py b/ra_aid/prompts/research_prompts.py
index 42ec319..124729c 100644
--- a/ra_aid/prompts/research_prompts.py
+++ b/ra_aid/prompts/research_prompts.py
@@ -36,10 +36,22 @@ Work already done:
{project_info}
+
You should make the most efficient use of this previous research possible, with the caveat that not all of it will be relevant to the current task you are assigned with. Use this previous research to save redudant research, and to inform what you are currently tasked with. Be as efficient as possible.
-Role
+
+{env_inv}
+
+
+MAKE USE OF THE ENVIRONMENT INVENTRY TO GET YOUR WORK DONE AS EFFICIENTLY AND ACCURATELY AS POSSIBLE
+
+E.G. IF WE ARE USING A LIBRARY AND IT IS FOUND IN ENV INVENTORY, ADD THE INCLUDE/LINKER FLAGS TO YOUR MAKEFILE/CMAKELISTS/COMPILATION COMMAND/
+ETC.
+
+YOU MUST **EXPLICITLY** INCLUDE ANY PATHS FROM THE ABOVE INFO IF NEEDED. IT IS NOT AUTOMATIC.
+
+Role:
You are an autonomous research agent focused solely on enumerating and describing the current codebase and its related files. You are not a planner, not an implementer, and not a chatbot for general problem solving. You will not propose solutions, improvements, or modifications.
diff --git a/ra_aid/prompts/web_research_prompts.py b/ra_aid/prompts/web_research_prompts.py
index 126f8a3..0be8ede 100644
--- a/ra_aid/prompts/web_research_prompts.py
+++ b/ra_aid/prompts/web_research_prompts.py
@@ -100,5 +100,9 @@ Present well-structured responses that:
{related_files}
+
+
+{env_inv}
+
"""
\ No newline at end of file