11from typing import Optional
22import sys
3+ import traceback
34from pathlib import Path
45import importlib .util
56from dotenv import load_dotenv
1415MAIN_MODULE_NAME = "main"
1516
1617
18+ def _format_friendy_error_message (exception : Exception ):
19+ """
20+ Projects will throw various errors, especially on first runs, so we catch
21+ them here and print a more helpful message.
22+
23+ In order to prevent us from having to import all possible backend exceptions
24+ we do string matching on the exception type and traceback contents.
25+ """
26+ # TODO These end up being pretty framework-specific; consider individual implementations.
27+ COMMON_LLM_ENV_VARS = (
28+ 'OPENAI_API_KEY' ,
29+ 'ANTHROPIC_API_KEY' ,
30+ )
31+
32+ name = exception .__class__ .__name__
33+ message = str (exception )
34+ tracebacks = traceback .format_exception (type (exception ), exception , exception .__traceback__ )
35+
36+ match (name , message , tracebacks ):
37+ # The user doesn't have an environment variable set for the LLM provider.
38+ case ('AuthenticationError' , m , t ) if 'litellm.AuthenticationError' in t [- 1 ]:
39+ variable_name = [k for k in COMMON_LLM_ENV_VARS if k in message ] or ["correct" ]
40+ return (
41+ "We were unable to connect to the LLM provider. "
42+ f"Ensure your .env file has the { variable_name [0 ]} variable set."
43+ )
44+ # This happens when the LLM configured for an agent is invalid.
45+ case ('BadRequestError' , m , t ) if 'LLM Provider NOT provided' in t [- 1 ]:
46+ return (
47+ "An invalid LLM was configured for an agent. "
48+ "Ensure the 'llm' attribute of the agent in the agents.yaml file is in the format <provider>/<model>."
49+ )
50+ # The user has not configured the correct agent name in the tasks.yaml file.
51+ case ('KeyError' , m , t ) if 'self.tasks_config[task_name]["agent"]' in t [- 2 ]:
52+ return (
53+ f"The agent { message } is not defined in your agents file. "
54+ "Ensure the 'agent' fields in your tasks.yaml correspond to an entry in the agents.yaml file."
55+ )
56+ # The user does not have an agent defined in agents.yaml file, but it does
57+ # exist in the entrypoint code.
58+ case ('KeyError' , m , t ) if 'config=self.agents_config[' in t [- 2 ]:
59+ return (
60+ f"The agent { message } is not defined in your agents file. "
61+ "Ensure all agents referenced in your code are defined in the agents.yaml file."
62+ )
63+ # The user does not have a task defined in tasks.yaml file, but it does
64+ # exist in the entrypoint code.
65+ case ('KeyError' , m , t ) if 'config=self.tasks_config[' in t [- 2 ]:
66+ return (
67+ f"The task { message } is not defined in your tasks. "
68+ "Ensure all tasks referenced in your code are defined in the tasks.yaml file."
69+ )
70+ case (_, _, _):
71+ return f"{ name } : { message } , { tracebacks [- 1 ]} "
72+
73+
1774def _import_project_module (path : Path ):
1875 """
1976 Import `main` from the project path.
@@ -32,7 +89,7 @@ def _import_project_module(path: Path):
3289 return project_module
3390
3491
35- def run_project (command : str = 'run' , cli_args : Optional [str ] = None ):
92+ def run_project (command : str = 'run' , debug : bool = False , cli_args : Optional [str ] = None ):
3693 """Validate that the project is ready to run and then run it."""
3794 if conf .get_framework () not in frameworks .SUPPORTED_FRAMEWORKS :
3895 print (term_color (f"Framework { conf .get_framework ()} is not supported by agentstack." , 'red' ))
@@ -55,14 +112,18 @@ def run_project(command: str = 'run', cli_args: Optional[str] = None):
55112 load_dotenv (Path .home () / '.env' ) # load the user's .env file
56113 load_dotenv (conf .PATH / '.env' , override = True ) # load the project's .env file
57114
58- # import src/main.py from the project path
115+ # import src/main.py from the project path and run `command` from the project's main.py
59116 try :
117+ print ("Running your agent..." )
60118 project_main = _import_project_module (conf .PATH )
119+ getattr (project_main , command )()
61120 except ImportError as e :
62121 print (term_color (f"Failed to import project. Does '{ MAIN_FILENAME } ' exist?:\n { e } " , 'red' ))
63122 sys .exit (1 )
64-
65- # run `command` from the project's main.py
66- # TODO try/except this and print detailed information with a --debug flag
67- print ("Running your agent..." )
68- return getattr (project_main , command )()
123+ except Exception as exception :
124+ if debug :
125+ raise exception
126+ print (term_color ("\n An error occurred while running your project:\n " , 'red' ))
127+ print (_format_friendy_error_message (exception ))
128+ print (term_color ("\n Run `agentstack run --debug` for a full traceback." , 'blue' ))
129+ sys .exit (1 )
0 commit comments