11# app.py
2+ import importlib
3+ import sys
4+ from pathlib import Path
25from dotenv import load_dotenv
6+ from agentstack import conf , frameworks , inputs
7+ from agentstack .exceptions import ValidationError
8+ from agentstack .utils import verify_agentstack_project
9+ # TODO: move this to not cli, but cant be utils due to circular import
10+ from agentstack .cli .run import format_friendly_error_message
11+
312load_dotenv (dotenv_path = "/app/.env" )
413
514from flask import Flask , request , jsonify
615import requests
7- from typing import Dict , Any
16+ from typing import Dict , Any , Optional
817import os
9- from agentstack .run import run_project
18+
19+ MAIN_FILENAME : Path = Path ("src/main.py" )
20+ MAIN_MODULE_NAME = "main"
1021
1122app = Flask (__name__ )
1223
@@ -84,3 +95,49 @@ def process_agent():
8495 print ("Learn more about agent requests at https://docs.agentstack.sh/" ) # TODO: add docs for this
8596
8697 app .run (host = '0.0.0.0' , port = port )
98+
99+
100+ def run_project (command : str = 'run' , api_args : Optional [Dict [str , str ]] = None ,
101+ api_inputs : Optional [Dict [str , str ]] = None ):
102+ """Validate that the project is ready to run and then run it."""
103+ verify_agentstack_project ()
104+
105+ if conf .get_framework () not in frameworks .SUPPORTED_FRAMEWORKS :
106+ raise ValidationError (f"Framework { conf .get_framework ()} is not supported by agentstack." )
107+
108+ try :
109+ frameworks .validate_project ()
110+ except ValidationError as e :
111+ raise e
112+
113+ inputs .add_input_for_run (** api_inputs )
114+
115+ load_dotenv (Path .home () / '.env' ) # load the user's .env file
116+ load_dotenv (conf .PATH / '.env' , override = True ) # load the project's .env file
117+
118+ # import src/main.py from the project path and run `command` from the project's main.py
119+ try :
120+ log .notify ("Running your agent..." )
121+ project_main = _import_project_module (conf .PATH )
122+ getattr (project_main , command )()
123+ except ImportError as e :
124+ raise ValidationError (f"Failed to import AgentStack project at: { conf .PATH .absolute ()} \n { e } " )
125+ except Exception as e :
126+ raise Exception (format_friendly_error_message (e ))
127+
128+ def _import_project_module (path : Path ):
129+ """
130+ Import `main` from the project path.
131+
132+ We do it this way instead of spawning a subprocess so that we can share
133+ state with the user's project.
134+ """
135+ spec = importlib .util .spec_from_file_location (MAIN_MODULE_NAME , str (path / MAIN_FILENAME ))
136+
137+ assert spec is not None # appease type checker
138+ assert spec .loader is not None # appease type checker
139+
140+ project_module = importlib .util .module_from_spec (spec )
141+ sys .path .insert (0 , str ((path / MAIN_FILENAME ).parent ))
142+ spec .loader .exec_module (project_module )
143+ return project_module
0 commit comments