11"""Minimal demo script to run UiPathDevTerminal with mock runtimes."""
22
33import asyncio
4+ import logging
45from typing import Any , Optional
56
7+ from opentelemetry import trace
68from uipath .runtime import (
79 UiPathBaseRuntime ,
810 UiPathExecuteOptions ,
1214)
1315from uipath .runtime .schema import UiPathRuntimeSchema
1416
17+ logger = logging .getLogger (__name__ )
18+
1519
1620class MockRuntime (UiPathBaseRuntime ):
17- """A simple mock runtime that echoes its input ."""
21+ """A mock runtime that simulates a multi-step workflow with rich telemetry ."""
1822
1923 async def get_schema (self ) -> UiPathRuntimeSchema :
2024 return UiPathRuntimeSchema (
@@ -39,19 +43,207 @@ async def execute(
3943 options : Optional [UiPathExecuteOptions ] = None ,
4044 ) -> UiPathRuntimeResult :
4145 payload = input or {}
42- # Simulate some async work
43- await asyncio .sleep (0.2 )
46+
47+ tracer = trace .get_tracer ("uipath.dev.mock-runtime" )
48+
49+ execution_id = getattr (self .context , "job_id" , None ) or "mock-execution"
50+ entrypoint = getattr (self .context , "entrypoint" , None ) or "mock-entrypoint"
51+ message = str (payload .get ("message" , "" ))
52+ message_length = len (message )
53+
54+ with tracer .start_as_current_span (
55+ "mock-runtime.execute" ,
56+ attributes = {
57+ "uipath.runtime.name" : "MockRuntime" ,
58+ "uipath.runtime.type" : "agent" ,
59+ "uipath.execution.id" : execution_id ,
60+ "uipath.runtime.entrypoint" : entrypoint ,
61+ "uipath.input.message.length" : message_length ,
62+ "uipath.input.has_message" : "message" in payload ,
63+ },
64+ ) as root_span :
65+ logger .info (
66+ "MockRuntime: starting execution" ,
67+ extra = {
68+ "uipath.execution.id" : execution_id ,
69+ "uipath.runtime.entrypoint" : entrypoint ,
70+ },
71+ )
72+ print (f"[MockRuntime] Starting execution (execution_id={ execution_id } )" )
73+
74+ # Stage 1: Initialization
75+ with tracer .start_as_current_span (
76+ "initialize.environment" ,
77+ attributes = {
78+ "uipath.step.name" : "initialize-environment" ,
79+ "uipath.step.kind" : "init" ,
80+ "uipath.execution.id" : execution_id ,
81+ },
82+ ):
83+ logger .info ("MockRuntime: initializing environment" )
84+ print ("[MockRuntime] Initializing environment..." )
85+ await asyncio .sleep (0.5 )
86+
87+ # Stage 2: Validation
88+ with tracer .start_as_current_span (
89+ "validate.input" ,
90+ attributes = {
91+ "uipath.step.name" : "validate-input" ,
92+ "uipath.step.kind" : "validation" ,
93+ "uipath.execution.id" : execution_id ,
94+ "uipath.input.has_message" : "message" in payload ,
95+ },
96+ ) as validate_span :
97+ logger .info ("MockRuntime: validating input" )
98+ print ("[MockRuntime] Validating input..." )
99+ await asyncio .sleep (0.5 )
100+
101+ if "message" not in payload :
102+ logger .warning ("MockRuntime: missing 'message' in payload" )
103+ validate_span .set_attribute (
104+ "uipath.validation.missing_field" , "message"
105+ )
106+
107+ # Stage 3: Preprocessing
108+ with tracer .start_as_current_span (
109+ "preprocess.data" ,
110+ attributes = {
111+ "uipath.step.name" : "preprocess-data" ,
112+ "uipath.step.kind" : "preprocess" ,
113+ "uipath.execution.id" : execution_id ,
114+ "uipath.input.size.bytes" : len (str (payload ).encode ("utf-8" )),
115+ },
116+ ):
117+ logger .info ("MockRuntime: preprocessing data" )
118+ print ("[MockRuntime] Preprocessing data..." )
119+ await asyncio .sleep (0.5 )
120+
121+ # Stage 4: Compute / reasoning
122+ with tracer .start_as_current_span (
123+ "compute.result" ,
124+ attributes = {
125+ "uipath.step.name" : "compute-result" ,
126+ "uipath.step.kind" : "compute" ,
127+ "uipath.execution.id" : execution_id ,
128+ },
129+ ):
130+ logger .info ("MockRuntime: compute phase started" )
131+ print ("[MockRuntime] Compute phase..." )
132+
133+ # Subtask: embedding computation
134+ with tracer .start_as_current_span (
135+ "compute.embeddings" ,
136+ attributes = {
137+ "uipath.step.name" : "compute-embeddings" ,
138+ "uipath.step.kind" : "compute-subtask" ,
139+ "uipath.execution.id" : execution_id ,
140+ },
141+ ):
142+ logger .info ("MockRuntime: computing embeddings" )
143+ print ("[MockRuntime] Computing embeddings..." )
144+ await asyncio .sleep (0.5 )
145+
146+ # Subtask: KB query
147+ with tracer .start_as_current_span (
148+ "query.knowledgebase" ,
149+ attributes = {
150+ "uipath.step.name" : "query-knowledgebase" ,
151+ "uipath.step.kind" : "io" ,
152+ "uipath.execution.id" : execution_id ,
153+ "uipath.kb.query.length" : message_length ,
154+ },
155+ ):
156+ logger .info ("MockRuntime: querying knowledge base" )
157+ print ("[MockRuntime] Querying knowledge base..." )
158+ await asyncio .sleep (0.5 )
159+
160+ # Stage 5: Post-processing
161+ with tracer .start_as_current_span (
162+ "postprocess.results" ,
163+ attributes = {
164+ "uipath.step.name" : "postprocess-results" ,
165+ "uipath.step.kind" : "postprocess" ,
166+ "uipath.execution.id" : execution_id ,
167+ },
168+ ):
169+ logger .info ("MockRuntime: post-processing results" )
170+ print ("[MockRuntime] Post-processing results..." )
171+ await asyncio .sleep (0.4 )
172+
173+ with tracer .start_as_current_span (
174+ "generate.output" ,
175+ attributes = {
176+ "uipath.step.name" : "generate-output" ,
177+ "uipath.step.kind" : "postprocess-subtask" ,
178+ "uipath.execution.id" : execution_id ,
179+ },
180+ ):
181+ logger .info ("MockRuntime: generating structured output" )
182+ print ("[MockRuntime] Generating output..." )
183+ await asyncio .sleep (0.4 )
184+
185+ # Stage 6: Persistence
186+ with tracer .start_as_current_span (
187+ "persist.artifacts" ,
188+ attributes = {
189+ "uipath.step.name" : "persist-artifacts" ,
190+ "uipath.step.kind" : "io" ,
191+ "uipath.execution.id" : execution_id ,
192+ "uipath.persistence.enabled" : False ,
193+ },
194+ ):
195+ logger .info ("MockRuntime: persisting artifacts (mock)" )
196+ print ("[MockRuntime] Persisting artifacts (mock)..." )
197+ await asyncio .sleep (0.4 )
198+
199+ # Stage 7: Cleanup
200+ with tracer .start_as_current_span (
201+ "cleanup.resources" ,
202+ attributes = {
203+ "uipath.step.name" : "cleanup-resources" ,
204+ "uipath.step.kind" : "cleanup" ,
205+ "uipath.execution.id" : execution_id ,
206+ },
207+ ):
208+ logger .info ("MockRuntime: cleaning up resources" )
209+ print ("[MockRuntime] Cleaning up resources..." )
210+ await asyncio .sleep (0.3 )
211+
212+ result_payload = {
213+ "result" : f"Mock runtime processed: { payload .get ('message' , '<no message>' )} " ,
214+ "metadata" : {
215+ "execution_id" : execution_id ,
216+ "entrypoint" : entrypoint ,
217+ "message_length" : message_length ,
218+ },
219+ }
220+
221+ root_span .set_attribute ("uipath.runtime.status" , "success" )
222+ root_span .set_attribute ("uipath.runtime.duration.approx" , "5s" )
223+ root_span .set_attribute ("uipath.output.has_error" , False )
224+ root_span .set_attribute (
225+ "uipath.output.message_length" , len (str (result_payload ))
226+ )
227+
228+ logger .info (
229+ "MockRuntime: execution completed successfully" ,
230+ extra = {
231+ "uipath.execution.id" : execution_id ,
232+ "uipath.runtime.status" : "success" ,
233+ },
234+ )
235+ print (f"[MockRuntime] Finished successfully with result={ result_payload !r} " )
236+
44237 return UiPathRuntimeResult (
45- output = { "result" : f"Mock runtime got: { payload !r } " } ,
238+ output = result_payload ,
46239 status = UiPathRuntimeStatus .SUCCESSFUL ,
47240 )
48241
49242 async def cleanup (self ) -> None :
50- # Nothing to clean up in this mock
51- pass
243+ logger . info ( "MockRuntime: cleanup() invoked" )
244+ print ( "[MockRuntime] cleanup() invoked" )
52245
53246
54- # 2) Mock runtime factory
55247class MockRuntimeFactory (UiPathRuntimeFactory [MockRuntime ]):
56248 """Runtime factory compatible with UiPathDevTerminal expectations."""
57249
0 commit comments