@@ -124,10 +124,13 @@ def __init__(
124124 sandbox_path = os .path .join ("sandbox" , session_id )
125125
126126 self .sandbox_path = os .path .abspath (sandbox_path )
127+ self .original_cwd = os .getcwd () # Store original working directory
127128 os .makedirs (self .sandbox_path , exist_ok = True )
129+
128130 print (f"📁 Sandbox mode enabled: { self .sandbox_path } " )
129131 else :
130132 self .sandbox_path = None
133+ self .original_cwd = None
131134
132135 # Display configuration in a nice, readable format
133136 print ("\n " + "=" * 50 )
@@ -167,6 +170,10 @@ def __init__(
167170 print (f" Enabled: True" )
168171 print (f" Sandbox Path: { self .sandbox_path } " )
169172 print (f" Files will be created in: { self .sandbox_path } " )
173+ print (f" Original Project Path: { self .original_cwd } " )
174+ print (" Data Access:" )
175+ print (" - Relative paths: ./data/... (via symlinks)" )
176+ print (" - Helper function: get_project_path('data/...') for absolute paths" )
170177
171178 print ("=" * 50 + "\n " )
172179
@@ -176,6 +183,10 @@ def __init__(
176183 os .makedirs (path )
177184 print (f"Created directory: { path } " )
178185
186+ # Setup sandbox data access after path is assigned
187+ if self .sandbox_mode :
188+ self ._setup_sandbox_data_access ()
189+
179190 # --- Begin custom folder/file checks ---
180191 benchmark_dir = os .path .join (path , "biomni_data" , "benchmark" )
181192 data_lake_dir = os .path .join (path , "biomni_data" , "data_lake" )
@@ -1415,9 +1426,9 @@ def execute(state: AgentState) -> AgentState:
14151426 # Inject custom functions into the Python execution environment
14161427 self ._inject_custom_functions_to_repl ()
14171428
1418- # Pass sandbox path if sandbox mode is enabled
1429+ # Pass sandbox path and original directory if sandbox mode is enabled
14191430 if self .sandbox_mode and self .sandbox_path :
1420- result = run_with_timeout (run_python_repl , [code , self .sandbox_path ], timeout = timeout )
1431+ result = run_with_timeout (run_python_repl , [code , self .sandbox_path , self . original_cwd ], timeout = timeout )
14211432 else :
14221433 result = run_with_timeout (run_python_repl , [code ], timeout = timeout )
14231434
@@ -1929,6 +1940,46 @@ def get_sandbox_path(self) -> str | None:
19291940 """
19301941 return self .sandbox_path if self .sandbox_mode else None
19311942
1943+ def _setup_sandbox_data_access (self ) -> None :
1944+ """Setup data access for sandbox mode by creating symbolic links to important directories."""
1945+ if not self .sandbox_mode or not self .sandbox_path :
1946+ return
1947+
1948+ # List of important directories/files to link into sandbox
1949+ important_paths = [
1950+ ("data" , os .path .join (self .original_cwd , "data" )),
1951+ ("biomni_data" , os .path .join (self .original_cwd , "data" , "biomni_data" )),
1952+ ]
1953+
1954+ # Create symbolic links for data access
1955+ for link_name , target_path in important_paths :
1956+ if os .path .exists (target_path ):
1957+ sandbox_link = os .path .join (self .sandbox_path , link_name )
1958+
1959+ # Remove existing link if it exists
1960+ if os .path .islink (sandbox_link ):
1961+ os .unlink (sandbox_link )
1962+ elif os .path .exists (sandbox_link ):
1963+ # Don't overwrite real directories/files
1964+ continue
1965+
1966+ try :
1967+ os .symlink (target_path , sandbox_link )
1968+ print (f"🔗 Linked { link_name } -> { target_path } " )
1969+ except OSError as e :
1970+ print (f"⚠️ Could not create symlink { link_name } : { e } " )
1971+
1972+ # Also try to link the main data directory directly if path is provided
1973+ main_data_path = os .path .join (self .original_cwd , self .path )
1974+ if os .path .exists (main_data_path ) and main_data_path != os .path .join (self .original_cwd , "data" ):
1975+ sandbox_data_link = os .path .join (self .sandbox_path , "main_data" )
1976+ if not os .path .exists (sandbox_data_link ):
1977+ try :
1978+ os .symlink (main_data_path , sandbox_data_link )
1979+ print (f"🔗 Linked main_data -> { main_data_path } " )
1980+ except OSError as e :
1981+ print (f"⚠️ Could not create main_data symlink: { e } " )
1982+
19321983 def save_conversation_history (self , filepath : str , include_images : bool = True , save_pdf : bool = True ) -> None :
19331984 """Save the complete conversation history as PDF only.
19341985
0 commit comments