77from pathlib import Path
88from typing import Any
99
10- from pydantic import BaseModel , ConfigDict
10+ from pydantic import BaseModel , ConfigDict , Field
1111from uipath .core .errors import UiPathFaultedTriggerError
1212from uipath .core .tracing import UiPathTraceManager
1313
@@ -41,14 +41,38 @@ class UiPathRuntimeContext(BaseModel):
4141 folder_key : str | None = None
4242 process_key : str | None = None
4343 config_path : str = "uipath.json"
44- runtime_dir : str | None = "__uipath"
45- result_file : str = "output.json"
46- state_file : str = "state.db"
47- input_file : str | None = None
48- output_file : str | None = None
49- trace_file : str | None = None
50- logs_file : str | None = "execution.log"
51- logs_min_level : str | None = "INFO"
44+ runtime_dir : str | None = Field (
45+ "__uipath" , description = "Directory for runtime files"
46+ )
47+ result_file : str = Field (
48+ "output.json" , description = "Filename for the result output"
49+ )
50+ result_file_path : str | None = Field (
51+ None ,
52+ description = (
53+ "Full path override for the result file. "
54+ "When specified, takes priority over runtime_dir + result_file. "
55+ "If not specified, path is constructed from runtime_dir and result_file."
56+ ),
57+ )
58+ state_file : str = Field ("state.db" , description = "Filename for the state database" )
59+ state_file_path : str | None = Field (
60+ None ,
61+ description = (
62+ "Full path override for the state file. "
63+ "When specified, takes priority over runtime_dir + state_file. "
64+ "If not specified, path is constructed from runtime_dir and state_file."
65+ ),
66+ )
67+ input_file : str | None = Field (None , description = "Full path to the input JSON file" )
68+ output_file : str | None = Field (
69+ None , description = "Full path to the output JSON file"
70+ )
71+ trace_file : str | None = Field (None , description = "Full path to the trace file" )
72+ logs_file : str | None = Field (
73+ "execution.log" , description = "Filename for the logs file"
74+ )
75+ logs_min_level : str | None = Field ("INFO" , description = "Minimum log level" )
5276 result : UiPathRuntimeResult | None = None
5377 trace_manager : UiPathTraceManager | None = None
5478
@@ -197,7 +221,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
197221 # Always write output file at runtime, except for inner runtimes
198222 # Inner runtimes have execution_id
199223 if self .job_id :
200- with open (self .result_file_path , "w" ) as f :
224+ with open (self .resolved_result_file_path , "w" ) as f :
201225 json .dump (content , f , indent = 2 , default = str )
202226
203227 # Write the execution output to file if requested
@@ -230,7 +254,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
230254 )
231255 error_result_content = error_result .to_dict ()
232256 if self .job_id :
233- with open (self .result_file_path , "w" ) as f :
257+ with open (self .resolved_result_file_path , "w" ) as f :
234258 json .dump (error_result_content , f , indent = 2 , default = str )
235259 except Exception as write_error :
236260 logger .error (f"Failed to write error output file: { str (write_error )} " )
@@ -251,16 +275,24 @@ def __exit__(self, exc_type, exc_val, exc_tb):
251275 self .logs_interceptor .teardown ()
252276
253277 @cached_property
254- def result_file_path (self ) -> str :
278+ def resolved_result_file_path (self ) -> str :
255279 """Get the full path to the result file."""
280+ # If full path is explicitly specified, use that
281+ if self .result_file_path :
282+ return self .result_file_path
283+ # Otherwise, construct from runtime_dir and result_file
256284 if self .runtime_dir and self .result_file :
257285 os .makedirs (self .runtime_dir , exist_ok = True )
258286 return os .path .join (self .runtime_dir , self .result_file )
259287 return os .path .join ("__uipath" , "output.json" )
260288
261289 @cached_property
262- def state_file_path (self ) -> str :
290+ def resolved_state_file_path (self ) -> str :
263291 """Get the full path to the state file."""
292+ # If full path is explicitly specified, use that
293+ if self .state_file_path :
294+ return self .state_file_path
295+ # Otherwise, construct from runtime_dir and state_file
264296 if self .runtime_dir and self .state_file :
265297 os .makedirs (self .runtime_dir , exist_ok = True )
266298 return os .path .join (self .runtime_dir , self .state_file )
0 commit comments