44import logging
55import os
66from functools import cached_property
7+ from pathlib import Path
78from typing import (
89 Any ,
910 TypeVar ,
@@ -29,7 +30,7 @@ class UiPathRuntimeContext(BaseModel):
2930 """Context information passed throughout the runtime execution."""
3031
3132 entrypoint : str | None = None
32- input : dict [ str , Any ] | None = None
33+ input : str | None = None
3334 job_id : str | None = None
3435 config_path : str = "uipath.json"
3536 runtime_dir : str | None = "__uipath"
@@ -44,34 +45,99 @@ class UiPathRuntimeContext(BaseModel):
4445
4546 model_config = ConfigDict (arbitrary_types_allowed = True , extra = "allow" )
4647
47- def __enter__ (self ):
48- """Async enter method called when entering the 'async with' block .
48+ def get_input (self ) -> dict [ str , Any ] :
49+ """Get parsed input data .
4950
50- Initializes and prepares the runtime contextual environment.
51+ Priority:
52+ 1. If input_file is specified, read and parse from file
53+ 2. Otherwise, parse the input string
5154
5255 Returns:
53- The runtime context instance
56+ Parsed input dictionary
57+
58+ Raises:
59+ UiPathRuntimeError: If JSON is invalid or file not found
5460 """
61+ if self .input_file :
62+ return self ._read_input_from_file (self .input_file )
63+
64+ return self ._parse_input_string (self .input )
65+
66+ def _read_input_from_file (self , file_path : str ) -> dict [str , Any ]:
67+ """Read and parse input from JSON file."""
68+ path = Path (file_path )
69+
70+ # Validate file extension
71+ if path .suffix != ".json" :
72+ raise UiPathRuntimeError (
73+ code = UiPathErrorCode .INVALID_INPUT_FILE_EXTENSION ,
74+ title = "Invalid Input File Extension" ,
75+ detail = f"The provided input file must be in JSON format. Got: { path .suffix } " ,
76+ category = UiPathErrorCategory .USER ,
77+ )
78+
79+ # Check if file exists
80+ if not path .exists ():
81+ raise UiPathRuntimeError (
82+ code = UiPathErrorCode .MISSING_INPUT_FILE ,
83+ title = "Input File Not Found" ,
84+ detail = f"The input file does not exist: { file_path } " ,
85+ category = UiPathErrorCategory .USER ,
86+ )
87+
5588 try :
56- if self .input_file :
57- # Read the input from file if provided
58- _ , file_extension = os .path .splitext (self .input_file )
59- if file_extension != ".json" :
60- raise UiPathRuntimeError (
61- code = UiPathErrorCode .INVALID_INPUT_FILE_EXTENSION ,
62- title = "Invalid Input File Extension" ,
63- detail = "The provided input file must be in JSON format." ,
64- )
65- with open (self .input_file ) as f :
66- self .input = json .loads (f .read ())
89+ with open (path ) as f :
90+ return json .load (f )
91+ except json .JSONDecodeError as e :
92+ raise UiPathRuntimeError (
93+ code = UiPathErrorCode .INPUT_INVALID_JSON ,
94+ title = "Invalid JSON in Input File" ,
95+ detail = f"The input file contains invalid JSON: { e } " ,
96+ category = UiPathErrorCategory .USER ,
97+ ) from e
98+ except Exception as e :
99+ raise UiPathRuntimeError (
100+ code = UiPathErrorCode .INPUT_INVALID_JSON ,
101+ title = "Failed to Read Input File" ,
102+ detail = f"Error reading input file: { e } " ,
103+ category = UiPathErrorCategory .SYSTEM ,
104+ ) from e
105+
106+ def _parse_input_string (self , input_str : str | None ) -> dict [str , Any ]:
107+ """Parse input from JSON string."""
108+ if not input_str or input_str .strip () == "" :
109+ return {}
110+
111+ try :
112+ parsed = json .loads (input_str )
113+
114+ # Ensure we return a dict
115+ if not isinstance (parsed , dict ):
116+ raise UiPathRuntimeError (
117+ code = UiPathErrorCode .INPUT_INVALID_JSON ,
118+ title = "Invalid Input Type" ,
119+ detail = f"Input must be a JSON object, got: { type (parsed ).__name__ } " ,
120+ category = UiPathErrorCategory .USER ,
121+ )
122+
123+ return parsed
124+
67125 except json .JSONDecodeError as e :
68126 raise UiPathRuntimeError (
69- UiPathErrorCode .INPUT_INVALID_JSON ,
70- "Invalid JSON input " ,
71- f"The input data is not valid JSON: { str ( e ) } " ,
72- UiPathErrorCategory .USER ,
127+ code = UiPathErrorCode .INPUT_INVALID_JSON ,
128+ title = "Invalid JSON Input " ,
129+ detail = f"The input data is not valid JSON: { e } " ,
130+ category = UiPathErrorCategory .USER ,
73131 ) from e
74132
133+ def __enter__ (self ):
134+ """Enter method called when entering the 'async with' block.
135+
136+ Initializes and prepares the runtime contextual environment.
137+
138+ Returns:
139+ The runtime context instance
140+ """
75141 # Intercept all stdout/stderr/logs
76142 # Write to file (runtime), stdout (debug) or log handler (if provided)
77143 self .logs_interceptor = UiPathRuntimeLogsInterceptor (
@@ -194,6 +260,7 @@ def with_defaults(cls: type[C], config_path: str | None = None, **kwargs) -> C:
194260 )
195261
196262 base = cls .from_config (resolved_config_path )
263+ base .config_path = resolved_config_path
197264
198265 bool_map = {"true" : True , "false" : False }
199266 tracing_enabled = os .environ .get ("UIPATH_TRACING_ENABLED" , True )
0 commit comments