uipath 2.1.30__py3-none-any.whl → 2.1.32__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  import asyncio
2
2
  import json
3
+ import traceback
3
4
  from datetime import datetime
4
5
  from os import environ as env
5
6
  from pathlib import Path
@@ -9,15 +10,19 @@ from uuid import uuid4
9
10
  from textual.app import App, ComposeResult
10
11
  from textual.binding import Binding
11
12
  from textual.containers import Container, Horizontal
12
- from textual.widgets import Button, ListView
13
+ from textual.widgets import Button, Footer, ListView
13
14
 
14
15
  from ..._runtime._contracts import (
16
+ UiPathErrorContract,
15
17
  UiPathRuntimeContext,
18
+ UiPathRuntimeError,
16
19
  UiPathRuntimeFactory,
20
+ UiPathRuntimeStatus,
17
21
  )
18
22
  from ._components._details import RunDetailsPanel
19
23
  from ._components._history import RunHistoryPanel
20
24
  from ._components._new import NewRunPanel
25
+ from ._components._resume import ResumePanel
21
26
  from ._models._execution import ExecutionRun
22
27
  from ._models._messages import LogMessage, TraceMessage
23
28
  from ._traces._exporter import RunContextExporter
@@ -31,8 +36,8 @@ class UiPathDevTerminal(App[Any]):
31
36
 
32
37
  BINDINGS = [
33
38
  Binding("q", "quit", "Quit"),
34
- Binding("n", "new_run", "New Run"),
35
- Binding("r", "execute_run", "Execute"),
39
+ Binding("n", "new_run", "New"),
40
+ Binding("r", "execute_run", "Run"),
36
41
  Binding("c", "clear_history", "Clear History"),
37
42
  Binding("escape", "cancel", "Cancel"),
38
43
  ]
@@ -73,6 +78,8 @@ class UiPathDevTerminal(App[Any]):
73
78
  # Run details panel (initially hidden)
74
79
  yield RunDetailsPanel(id="details-panel", classes="hidden")
75
80
 
81
+ yield Footer()
82
+
76
83
  async def on_button_pressed(self, event: Button.Pressed) -> None:
77
84
  """Handle button press events."""
78
85
  if event.button.id == "new-run-btn":
@@ -81,6 +88,8 @@ class UiPathDevTerminal(App[Any]):
81
88
  await self.action_execute_run()
82
89
  elif event.button.id == "cancel-btn":
83
90
  await self.action_cancel()
91
+ elif event.button.id == "resume-btn":
92
+ await self.action_resume()
84
93
 
85
94
  async def on_list_view_selected(self, event: ListView.Selected) -> None:
86
95
  """Handle run selection from history."""
@@ -104,6 +113,19 @@ class UiPathDevTerminal(App[Any]):
104
113
  """Cancel and return to new run view."""
105
114
  await self.action_new_run()
106
115
 
116
+ async def action_resume(self) -> None:
117
+ """Resume the suspended run."""
118
+ details_panel = self.query_one("#details-panel", RunDetailsPanel)
119
+ if details_panel and details_panel.current_run:
120
+ input: Dict[str, Any] = {}
121
+ input_data = self.query_one("#resume-panel", ResumePanel).get_input_values()
122
+ try:
123
+ input = json.loads(input_data)
124
+ except json.JSONDecodeError:
125
+ return
126
+ details_panel.current_run.input_data = input
127
+ asyncio.create_task(self._execute_runtime(details_panel.current_run))
128
+
107
129
  async def action_execute_run(self) -> None:
108
130
  """Execute a new run with UiPath runtime."""
109
131
  new_run_panel = self.query_one("#new-run-panel", NewRunPanel)
@@ -112,12 +134,14 @@ class UiPathDevTerminal(App[Any]):
112
134
  if not entrypoint:
113
135
  return
114
136
 
137
+ input: Dict[str, Any] = {}
115
138
  try:
116
- json.loads(input_data)
139
+ input = json.loads(input_data)
117
140
  except json.JSONDecodeError:
118
141
  return
119
142
 
120
- run = ExecutionRun(entrypoint, input_data)
143
+ run = ExecutionRun(entrypoint, input)
144
+
121
145
  self.runs[run.id] = run
122
146
 
123
147
  self._add_run_in_history(run)
@@ -137,7 +161,7 @@ class UiPathDevTerminal(App[Any]):
137
161
  try:
138
162
  context: UiPathRuntimeContext = self.runtime_factory.new_context(
139
163
  entrypoint=run.entrypoint,
140
- input=run.input_data,
164
+ input_json=run.input_data,
141
165
  trace_id=str(uuid4()),
142
166
  execution_id=run.id,
143
167
  logs_min_level=env.get("LOG_LEVEL", "INFO"),
@@ -146,24 +170,46 @@ class UiPathDevTerminal(App[Any]):
146
170
  ),
147
171
  )
148
172
 
149
- self._add_info_log(run, f"Starting execution: {run.entrypoint}")
173
+ if run.status == "suspended":
174
+ context.resume = True
175
+ self._add_info_log(run, f"Resuming execution: {run.entrypoint}")
176
+ else:
177
+ self._add_info_log(run, f"Starting execution: {run.entrypoint}")
178
+
179
+ run.status = "running"
180
+ run.start_time = datetime.now()
150
181
 
151
182
  result = await self.runtime_factory.execute_in_root_span(context)
152
183
 
153
184
  if result is not None:
154
- run.output_data = json.dumps(result.output)
185
+ if result.status == UiPathRuntimeStatus.SUSPENDED.value:
186
+ run.status = "suspended"
187
+ else:
188
+ run.output_data = result.output
189
+ run.status = "completed"
155
190
  if run.output_data:
156
191
  self._add_info_log(run, f"Execution result: {run.output_data}")
157
192
 
158
193
  self._add_info_log(run, "✅ Execution completed successfully")
159
- run.status = "completed"
160
194
  run.end_time = datetime.now()
161
195
 
196
+ except UiPathRuntimeError as e:
197
+ error_msg = (
198
+ f"{e.error_info.code}: {e.error_info.title}\n{e.error_info.detail}"
199
+ )
200
+ self._add_error_log(run, error_msg)
201
+ run.status = "failed"
202
+ run.end_time = datetime.now()
203
+ run.error = e.error_info
204
+
162
205
  except Exception as e:
163
206
  error_msg = f"Execution failed: {str(e)}"
164
207
  self._add_error_log(run, error_msg)
165
208
  run.status = "failed"
166
209
  run.end_time = datetime.now()
210
+ run.error = UiPathErrorContract(
211
+ code="Unknown", title=str(e), detail=traceback.format_exc()
212
+ )
167
213
 
168
214
  self._update_run_in_history(run)
169
215
  self._update_run_details(run)
@@ -1,3 +1,4 @@
1
+ import json
1
2
  from typing import Dict, List, Optional
2
3
 
3
4
  from textual.app import ComposeResult
@@ -8,6 +9,7 @@ from textual.widgets.tree import TreeNode
8
9
 
9
10
  from .._models._execution import ExecutionRun
10
11
  from .._models._messages import LogMessage, TraceMessage
12
+ from ._resume import ResumePanel
11
13
 
12
14
 
13
15
  class SpanDetailsDisplay(Container):
@@ -112,6 +114,9 @@ class RunDetailsPanel(Container):
112
114
  classes="detail-log",
113
115
  )
114
116
 
117
+ with TabPane("Resume", id="resume-tab"):
118
+ yield ResumePanel(id="resume-panel")
119
+
115
120
  def watch_current_run(
116
121
  self, old_value: Optional[ExecutionRun], new_value: Optional[ExecutionRun]
117
122
  ):
@@ -139,8 +144,14 @@ class RunDetailsPanel(Container):
139
144
  # Clear and rebuild traces tree using TraceMessage objects
140
145
  self._rebuild_spans_tree()
141
146
 
147
+ def _update_resume_tab(self, run: ExecutionRun) -> None:
148
+ resume_panel = self.query_one("#resume-panel", ResumePanel)
149
+ resume_panel.display = run.status == "suspended"
150
+
142
151
  def _show_run_details(self, run: ExecutionRun):
143
152
  """Display detailed information about the run in the Details tab."""
153
+ self._update_resume_tab(run)
154
+
144
155
  run_details_log = self.query_one("#run-details-log", RichLog)
145
156
  run_details_log.clear()
146
157
 
@@ -200,8 +211,6 @@ class RunDetailsPanel(Container):
200
211
  if isinstance(run.input_data, str):
201
212
  run_details_log.write(run.input_data)
202
213
  elif isinstance(run.input_data, dict):
203
- import json
204
-
205
214
  run_details_log.write(json.dumps(run.input_data, indent=2))
206
215
  else:
207
216
  run_details_log.write(str(run.input_data))
@@ -217,8 +226,6 @@ class RunDetailsPanel(Container):
217
226
  if isinstance(run.output_data, str):
218
227
  run_details_log.write(run.output_data)
219
228
  elif isinstance(run.output_data, dict):
220
- import json
221
-
222
229
  run_details_log.write(json.dumps(run.output_data, indent=2))
223
230
  else:
224
231
  run_details_log.write(str(run.output_data))
@@ -229,28 +236,12 @@ class RunDetailsPanel(Container):
229
236
  if hasattr(run, "error") and run.error:
230
237
  run_details_log.write("[bold red]ERROR:[/bold red]")
231
238
  run_details_log.write("[dim]" + "=" * 50 + "[/dim]")
232
- run_details_log.write(f"[red]{run.error}[/red]")
239
+ if run.error.code:
240
+ run_details_log.write(f"[red]Code: {run.error.code}[/red]")
241
+ run_details_log.write(f"[red]Title: {run.error.title}[/red]")
242
+ run_details_log.write(f"[red]\n{run.error.detail}[/red]")
233
243
  run_details_log.write("")
234
244
 
235
- # Additional metadata
236
- run_details_log.write("[bold]METADATA:[/bold]")
237
- run_details_log.write("[dim]" + "=" * 50 + "[/dim]")
238
-
239
- # Show available attributes
240
- for attr in ["id", "status", "start_time", "end_time", "duration_ms"]:
241
- if hasattr(run, attr):
242
- value = getattr(run, attr)
243
- if value is not None:
244
- run_details_log.write(f" {attr}: {value}")
245
-
246
- # Show traces count
247
- traces_count = len(run.traces) if run.traces else 0
248
- run_details_log.write(f" traces_count: {traces_count}")
249
-
250
- # Show logs count
251
- logs_count = len(run.logs) if run.logs else 0
252
- run_details_log.write(f" logs_count: {logs_count}")
253
-
254
245
  def _rebuild_spans_tree(self):
255
246
  """Rebuild the spans tree from current run's traces."""
256
247
  spans_tree = self.query_one("#spans-tree", Tree)
@@ -272,34 +263,38 @@ class RunDetailsPanel(Container):
272
263
  spans_tree = self.query_one("#spans-tree", Tree)
273
264
  root = spans_tree.root
274
265
 
275
- # Group spans by parent relationship
276
- root_spans = []
277
- child_spans: Dict[str, List[TraceMessage]] = {}
278
-
279
- for trace_msg in trace_messages:
280
- if not trace_msg.parent_span_id:
281
- root_spans.append(trace_msg)
282
- else:
283
- if trace_msg.parent_span_id not in child_spans:
284
- child_spans[trace_msg.parent_span_id] = []
285
- child_spans[trace_msg.parent_span_id].append(trace_msg)
266
+ # Filter out spans without parents (artificial root spans)
267
+ spans_by_id = {
268
+ msg.span_id: msg for msg in trace_messages if msg.parent_span_id is not None
269
+ }
286
270
 
287
- # Build tree recursively
271
+ # Build parent-to-children mapping once upfront
272
+ children_by_parent: Dict[str, List[TraceMessage]] = {}
273
+ for msg in spans_by_id.values():
274
+ if msg.parent_span_id:
275
+ if msg.parent_span_id not in children_by_parent:
276
+ children_by_parent[msg.parent_span_id] = []
277
+ children_by_parent[msg.parent_span_id].append(msg)
278
+
279
+ # Find root spans (parent doesn't exist in our filtered data)
280
+ root_spans = [
281
+ msg
282
+ for msg in trace_messages
283
+ if msg.parent_span_id and msg.parent_span_id not in spans_by_id
284
+ ]
285
+
286
+ # Build tree recursively for each root span
288
287
  for root_span in sorted(root_spans, key=lambda x: x.timestamp):
289
- if root_span.span_id in child_spans:
290
- for child in sorted(
291
- child_spans[root_span.span_id], key=lambda x: x.timestamp
292
- ):
293
- self._add_span_node(root, child, child_spans)
288
+ self._add_span_with_children(root, root_span, children_by_parent)
294
289
 
295
- def _add_span_node(
290
+ def _add_span_with_children(
296
291
  self,
297
292
  parent_node: TreeNode[str],
298
293
  trace_msg: TraceMessage,
299
- child_spans: Dict[str, List[TraceMessage]],
294
+ children_by_parent: Dict[str, List[TraceMessage]],
300
295
  ):
301
- """Recursively add span nodes to the tree."""
302
- # Create display label for the span
296
+ """Recursively add a span and all its children."""
297
+ # Create the node for this span
303
298
  color_map = {
304
299
  "started": "🔵",
305
300
  "running": "🟡",
@@ -308,26 +303,20 @@ class RunDetailsPanel(Container):
308
303
  "error": "🔴",
309
304
  }
310
305
  status_icon = color_map.get(trace_msg.status.lower(), "⚪")
311
-
312
306
  duration_str = (
313
307
  f" ({trace_msg.duration_ms:.1f}ms)" if trace_msg.duration_ms else ""
314
308
  )
315
309
  label = f"{status_icon} {trace_msg.span_name}{duration_str}"
316
310
 
317
- # Add node to tree
318
311
  node = parent_node.add(label)
319
- node.data = trace_msg.span_id # Store span_id for reference
312
+ node.data = trace_msg.span_id
320
313
  self.span_tree_nodes[trace_msg.span_id] = node
321
-
322
314
  node.expand()
323
315
 
324
- # Add child spans (sorted by timestamp)
325
- if trace_msg.span_id in child_spans:
326
- sorted_children = sorted(
327
- child_spans[trace_msg.span_id], key=lambda x: x.timestamp
328
- )
329
- for child_span in sorted_children:
330
- self._add_span_node(node, child_span, child_spans)
316
+ # Get children from prebuilt mapping - O(1) lookup
317
+ children = children_by_parent.get(trace_msg.span_id, [])
318
+ for child in sorted(children, key=lambda x: x.timestamp):
319
+ self._add_span_with_children(node, child, children_by_parent)
331
320
 
332
321
  def on_tree_node_selected(self, event: Tree.NodeSelected[str]) -> None:
333
322
  """Handle span selection in the tree."""
@@ -2,7 +2,14 @@ from typing import List, Optional
2
2
 
3
3
  from textual.app import ComposeResult
4
4
  from textual.containers import Container, Vertical
5
- from textual.widgets import Button, ListItem, ListView, Static
5
+ from textual.widgets import (
6
+ Button,
7
+ ListItem,
8
+ ListView,
9
+ Static,
10
+ TabbedContent,
11
+ TabPane,
12
+ )
6
13
 
7
14
  from .._models._execution import ExecutionRun
8
15
 
@@ -16,11 +23,16 @@ class RunHistoryPanel(Container):
16
23
  self.selected_run: Optional[ExecutionRun] = None
17
24
 
18
25
  def compose(self) -> ComposeResult:
19
- with Vertical():
20
- yield ListView(id="run-list", classes="run-list")
21
- yield Button(
22
- "+ New Run", id="new-run-btn", variant="primary", classes="new-run-btn"
23
- )
26
+ with TabbedContent():
27
+ with TabPane("History", id="history-tab"):
28
+ with Vertical():
29
+ yield ListView(id="run-list", classes="run-list")
30
+ yield Button(
31
+ "+ New",
32
+ id="new-run-btn",
33
+ variant="primary",
34
+ classes="new-run-btn",
35
+ )
24
36
 
25
37
  def add_run(self, run: ExecutionRun):
26
38
  """Add a new run to history."""
@@ -5,7 +5,7 @@ from typing import Any, Dict, Tuple, cast
5
5
  from textual.app import ComposeResult
6
6
  from textual.containers import Container, Horizontal, Vertical
7
7
  from textual.reactive import reactive
8
- from textual.widgets import Button, Select, TextArea
8
+ from textual.widgets import Button, Select, TabbedContent, TabPane, TextArea
9
9
 
10
10
 
11
11
  def mock_json_from_schema(schema: Dict[str, Any]) -> Dict[str, Any]:
@@ -63,32 +63,31 @@ class NewRunPanel(Container):
63
63
  )
64
64
 
65
65
  def compose(self) -> ComposeResult:
66
- with Vertical():
67
- options = [(path, path) for path in self.entrypoint_paths]
68
- yield Select(
69
- options,
70
- id="entrypoint-select",
71
- value=self.selected_entrypoint,
72
- allow_blank=False,
73
- )
74
-
75
- yield TextArea(
76
- text=self.initial_input,
77
- language="json",
78
- id="json-input",
79
- classes="input-field json-input",
80
- )
81
-
82
- with Horizontal(classes="run-actions"):
83
- yield Button(
84
- "▶ Run", id="execute-btn", variant="primary", classes="action-btn"
85
- )
86
- yield Button(
87
- "Cancel",
88
- id="cancel-btn",
89
- variant="default",
90
- classes="action-btn cancel-btn",
91
- )
66
+ with TabbedContent():
67
+ with TabPane("New run", id="new-tab"):
68
+ with Vertical():
69
+ options = [(path, path) for path in self.entrypoint_paths]
70
+ yield Select(
71
+ options,
72
+ id="entrypoint-select",
73
+ value=self.selected_entrypoint,
74
+ allow_blank=False,
75
+ )
76
+
77
+ yield TextArea(
78
+ text=self.initial_input,
79
+ language="json",
80
+ id="json-input",
81
+ classes="input-field json-input",
82
+ )
83
+
84
+ with Horizontal(classes="run-actions"):
85
+ yield Button(
86
+ "▶ Run",
87
+ id="execute-btn",
88
+ variant="primary",
89
+ classes="action-btn",
90
+ )
92
91
 
93
92
  async def on_select_changed(self, event: Select.Changed) -> None:
94
93
  """Update JSON input when user selects an entrypoint."""
@@ -0,0 +1,31 @@
1
+ from textual.app import ComposeResult
2
+ from textual.containers import Container, Horizontal, Vertical
3
+ from textual.widgets import Button, TextArea
4
+
5
+
6
+ class ResumePanel(Container):
7
+ """Panel for resuming a suspended run."""
8
+
9
+ def __init__(self, **kwargs):
10
+ super().__init__(**kwargs)
11
+
12
+ def compose(self) -> ComposeResult:
13
+ with Vertical():
14
+ yield TextArea(
15
+ text="{}",
16
+ language="json",
17
+ id="resume-json-input",
18
+ classes="input-field json-input",
19
+ )
20
+ with Horizontal(classes="run-actions"):
21
+ yield Button(
22
+ "▶ Resume",
23
+ id="resume-btn",
24
+ variant="primary",
25
+ classes="action-btn",
26
+ )
27
+
28
+ def get_input_values(self) -> str:
29
+ """Return the JSON text to resume with."""
30
+ json_input = self.query_one("#resume-json-input", TextArea)
31
+ return json_input.text.strip()
@@ -1,24 +1,28 @@
1
1
  import os
2
2
  from datetime import datetime
3
- from typing import List, Optional
3
+ from typing import Any, Dict, List, Optional
4
4
  from uuid import uuid4
5
5
 
6
+ from rich.text import Text
7
+
8
+ from ...._runtime._contracts import UiPathErrorContract
6
9
  from ._messages import LogMessage, TraceMessage
7
10
 
8
11
 
9
12
  class ExecutionRun:
10
13
  """Represents a single execution run."""
11
14
 
12
- def __init__(self, entrypoint: str, input_data: str):
15
+ def __init__(self, entrypoint: str, input_data: Dict[str, Any]):
13
16
  self.id = str(uuid4())[:8]
14
17
  self.entrypoint = entrypoint
15
18
  self.input_data = input_data
16
- self.output_data: Optional[str] = None
19
+ self.output_data: Optional[Dict[str, Any]] = None
17
20
  self.start_time = datetime.now()
18
21
  self.end_time: Optional[datetime] = None
19
22
  self.status = "running" # running, completed, failed
20
23
  self.traces: List[TraceMessage] = []
21
24
  self.logs: List[LogMessage] = []
25
+ self.error: Optional[UiPathErrorContract] = None
22
26
 
23
27
  @property
24
28
  def duration(self) -> str:
@@ -30,14 +34,32 @@ class ExecutionRun:
30
34
  return f"{delta.total_seconds():.1f}s"
31
35
 
32
36
  @property
33
- def display_name(self) -> str:
34
- status_icon = {"running": "⚙️", "completed": "✅", "failed": "❌"}.get(
35
- self.status, ""
36
- )
37
+ def display_name(self) -> Text:
38
+ status_colors = {
39
+ "running": "yellow",
40
+ "suspended": "cyan",
41
+ "completed": "green",
42
+ "failed": "red",
43
+ }
44
+
45
+ status_icon = {
46
+ "running": "▶",
47
+ "suspended": "⏸",
48
+ "completed": "✔",
49
+ "failed": "✖",
50
+ }.get(self.status, "?")
37
51
 
38
52
  script_name = (
39
53
  os.path.basename(self.entrypoint) if self.entrypoint else "untitled"
40
54
  )
55
+ truncated_script = script_name[:10]
41
56
  time_str = self.start_time.strftime("%H:%M:%S")
57
+ duration_str = self.duration[:6]
58
+
59
+ text = Text()
60
+ text.append(f"{status_icon:<2} ", style=status_colors.get(self.status, "white"))
61
+ text.append(f"{truncated_script:<10} ")
62
+ text.append(f"({time_str:<8}) ")
63
+ text.append(f"[{duration_str:<6}]")
42
64
 
43
- return f"{status_icon} {script_name} ({time_str}) [{self.duration}]"
65
+ return text
@@ -1,11 +1,7 @@
1
- /* Global layout - dark terminal theme */
2
1
  Screen {
3
- background: #1a1a1a;
4
- color: #e0e0e0;
5
2
  layout: horizontal;
6
3
  }
7
4
 
8
- /* Left sidebar - run history with embedded title */
9
5
  .run-history {
10
6
  width: 30%;
11
7
  min-width: 25;
@@ -15,18 +11,10 @@ Screen {
15
11
  .run-list {
16
12
  height: 1fr;
17
13
  margin-bottom: 1;
18
- border: solid #404040;
19
- background: #252525;
20
14
  }
21
15
 
22
16
  .run-item {
23
17
  padding: 0 1;
24
- background: transparent;
25
- color: #e0e0e0;
26
- }
27
-
28
- .run-item:hover {
29
- background: #333333;
30
18
  }
31
19
 
32
20
  .run-running {
@@ -47,43 +35,27 @@ Screen {
47
35
  .new-run-btn {
48
36
  width: 100%;
49
37
  margin-bottom: 1;
50
- background: #00d4ff;
51
- color: #000000;
52
38
  border: none;
53
39
  text-style: bold;
54
40
  }
55
-
56
- .new-run-btn:hover {
57
- background: #00a0cc;
58
- }
59
-
60
- /* Main content area */
61
41
  .main-content {
62
42
  width: 70%;
63
43
  padding-left: 1;
64
44
  }
65
45
 
66
- /* New run panel with embedded titles */
67
46
  .new-run-title {
68
- color: #00d4ff;
69
47
  text-style: bold;
70
- background: #252525;
71
48
  padding: 0 1;
72
49
  height: 1;
73
- border: solid #404040;
74
50
  margin-bottom: 0;
75
51
  }
76
52
 
77
53
  .new-run-panel {
78
54
  height: 100%;
79
- background: #252525;
80
- border: solid #404040;
81
55
  }
82
56
 
83
57
  .field-label {
84
- color: #00d4ff;
85
58
  text-style: bold;
86
- background: #252525;
87
59
  }
88
60
 
89
61
  .run-actions {
@@ -94,26 +66,10 @@ Screen {
94
66
  .action-btn {
95
67
  margin-right: 2;
96
68
  min-width: 8;
97
- background: #00ff88;
98
- color: #000000;
99
69
  border: none;
100
70
  text-style: bold;
101
71
  }
102
72
 
103
- .action-btn:hover {
104
- background: #00cc66;
105
- }
106
-
107
- .cancel-btn {
108
- background: #404040;
109
- color: #e0e0e0;
110
- }
111
-
112
- .cancel-btn:hover {
113
- background: #555555;
114
- }
115
-
116
- /* Run details panel with embedded titles */
117
73
  .details-content {
118
74
  height: 1fr;
119
75
  }
@@ -134,12 +90,10 @@ Screen {
134
90
 
135
91
  .detail-log {
136
92
  height: 1fr;
137
- background: #252525;
138
93
  padding: 1;
139
94
  padding-top: 0;
140
95
  }
141
96
 
142
- /* Status indicators for buttons */
143
97
  .status-running {
144
98
  background: #ffaa00;
145
99
  color: #000000;
@@ -158,53 +112,16 @@ Screen {
158
112
  border: solid #ff4444;
159
113
  }
160
114
 
161
- /* ListView styling */
162
- ListView {
163
- background: transparent;
164
- }
165
-
166
- ListView>ListItem {
167
- background: transparent;
168
- }
169
-
170
- ListView>ListItem:hover {
171
- background: #333333;
172
- }
173
-
174
- ListView>ListItem.--highlight {
175
- background: #00d4ff;
176
- color: #000000;
177
- }
178
-
179
- /* TextArea and RichLog improvements */
180
- TextArea {
181
- background: #1a1a1a;
182
- color: #e0e0e0;
183
- }
184
-
185
- RichLog {
186
- background: #252525;
187
- color: #e0e0e0;
188
- }
189
-
190
- /* Initially hide details panel */
191
115
  .hidden {
192
116
  display: none;
193
117
  }
194
118
 
195
- /* Header and Footer */
196
- Header {
197
- background: #000000;
198
- color: #00d4ff;
199
- }
200
-
201
119
  Footer {
202
- background: #000000;
203
- color: #888888;
204
- border-top: solid #404040;
120
+ margin-top:1;
121
+ height: auto;
122
+ dock: bottom;
205
123
  }
206
124
 
207
- /* Tabbed content styling */
208
125
  TabbedContent {
209
126
  height: 100%;
210
127
  }
@@ -214,7 +131,6 @@ TabPane {
214
131
  padding: 0;
215
132
  }
216
133
 
217
- /* Traces tab layout */
218
134
  .traces-content {
219
135
  height: 100%;
220
136
  }
@@ -231,60 +147,24 @@ TabPane {
231
147
  padding-left: 1;
232
148
  }
233
149
 
234
- /* Tree styling */
235
150
  .spans-tree {
236
151
  height: 100%;
237
- background: #252525;
238
152
  padding: 1;
239
153
  padding-top: 0;
240
154
  }
241
155
 
242
- Tree {
243
- background: #252525;
244
- color: #e0e0e0;
245
- }
246
-
247
- Tree>TreeNode {
248
- background: transparent;
249
- }
250
-
251
- Tree>TreeNode:hover {
252
- background: #333333;
253
- }
254
-
255
- Tree>TreeNode.--highlight {
256
- background: #00d4ff;
257
- color: #000000;
258
- }
259
-
260
- /* Tab styling */
261
- Tabs {
262
- background: #252525;
263
- color: #e0e0e0;
264
- }
265
-
266
- Tab {
267
- background: transparent;
268
- color: #888888;
269
- border: none;
270
- }
271
-
272
156
  Label {
273
157
  margin: 1 1;
274
158
  width: 100%;
275
159
  height: 100%;
276
- background: $panel;
277
160
  border: tall $primary;
278
161
  content-align: center middle;
279
162
  }
280
163
 
281
- /* Content areas */
282
164
  ContentSwitcher {
283
165
  height: 1fr;
284
- background: transparent;
285
166
  }
286
167
 
287
- /* Span details styling */
288
168
  SpanDetailsDisplay {
289
169
  height: 100%;
290
170
  }
@@ -297,35 +177,22 @@ SpanDetailsDisplay {
297
177
  height: 100%;
298
178
  }
299
179
 
300
- /* Panels */
301
180
  .new-run-panel {
302
181
  height: 100%;
303
- background: #252525;
304
- padding: 1;
305
182
  }
306
183
 
307
- /* Section Titles */
308
184
  .new-run-title {
309
- color: #00d4ff;
310
185
  text-style: bold;
311
- background: #1f1f1f;
312
186
  padding: 0 1;
313
187
  height: 2;
314
188
  content-align: left middle;
315
189
  }
316
190
 
317
- /* Labels */
318
191
  .field-label {
319
- color: #00d4ff;
320
192
  text-style: bold;
321
193
  margin: 1 0;
322
194
  }
323
195
 
324
- .input-field {
325
- background: #1a1a1a;
326
- color: #e0e0e0;
327
- }
328
-
329
196
  .script-input {
330
197
  height: 3;
331
198
  }
@@ -346,16 +213,3 @@ SpanDetailsDisplay {
346
213
  text-style: bold;
347
214
  border: none;
348
215
  }
349
-
350
- .action-btn:hover {
351
- background: #00cc66;
352
- }
353
-
354
- .cancel-btn {
355
- background: #404040;
356
- color: #e0e0e0;
357
- }
358
-
359
- .cancel-btn:hover {
360
- background: #555555;
361
- }
@@ -86,7 +86,7 @@ class UiPathRuntime(UiPathBaseRuntime):
86
86
  try:
87
87
  if self.context.input:
88
88
  self.context.input_json = json.loads(self.context.input)
89
- else:
89
+ if self.context.input_json is None:
90
90
  self.context.input_json = {}
91
91
  except json.JSONDecodeError as e:
92
92
  raise UiPathRuntimeError(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath
3
- Version: 2.1.30
3
+ Version: 2.1.32
4
4
  Summary: Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools.
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-python
@@ -31,13 +31,14 @@ uipath/_cli/_auth/auth_config.json,sha256=UnAhdum8phjuZaZKE5KLp0IcPCbIltDEU1M_G8
31
31
  uipath/_cli/_auth/index.html,sha256=uGK0CDTP8Rys_p4O_Pbd2x4tz0frKNVcumjrXnal5Nc,22814
32
32
  uipath/_cli/_auth/localhost.crt,sha256=oGl9oLLOiouHubAt39B4zEfylFvKEtbtr_43SIliXJc,1226
33
33
  uipath/_cli/_auth/localhost.key,sha256=X31VYXD8scZtmGA837dGX5l6G-LXHLo5ItWJhZXaz3c,1679
34
- uipath/_cli/_dev/_terminal/__init__.py,sha256=lKmYSkiHivGPHa70dVktkZ4o0gX4ijnLMOVoT6Q2AtQ,8263
35
- uipath/_cli/_dev/_terminal/_components/_details.py,sha256=7tK7EpeInALfpkbhuQudbEZAavZ2ZnRESFcslzpUXWE,15208
36
- uipath/_cli/_dev/_terminal/_components/_history.py,sha256=bpIm2uLP9sIP6v4meN0i4Pk2xOwVwXI4iPrWpQIzlDc,1807
37
- uipath/_cli/_dev/_terminal/_components/_new.py,sha256=81FVClAl_ou8B861PsgwU5flXFfxYVOLEr5gCdKia8c,4450
38
- uipath/_cli/_dev/_terminal/_models/_execution.py,sha256=ZjlBQ0AiArHPkDQZr-2P-AYnadN7wuy1F2Xb7Jsu9Ek,1386
34
+ uipath/_cli/_dev/_terminal/__init__.py,sha256=Fyqb5cQeP7B-zt5PEccusXxcOAlgCOsh792AUTBrdxc,10025
35
+ uipath/_cli/_dev/_terminal/_components/_details.py,sha256=DK1e6ZxuKws54G-4XfgGWNcEWZSTW5iQ2djHfvd365E,15055
36
+ uipath/_cli/_dev/_terminal/_components/_history.py,sha256=-0lystNcVUCUbHgEUVQ-CdxAfV3_X5uhjxWevxs19Z0,2054
37
+ uipath/_cli/_dev/_terminal/_components/_new.py,sha256=Lpt703Y_FTZ9tCrudcnDK7Dfta_7h6AEWqHJ9lR62sU,4577
38
+ uipath/_cli/_dev/_terminal/_components/_resume.py,sha256=_9nhlZOT7eaarzydugn8Z4ESHXuP-92U6XZyMSmXUwE,1002
39
+ uipath/_cli/_dev/_terminal/_models/_execution.py,sha256=4rMq-WWvhqLZfFB66_aCuGSkSYR4B1kUyegzWb2vm48,2052
39
40
  uipath/_cli/_dev/_terminal/_models/_messages.py,sha256=TR7D1yLL0PNYGUMts_cGLgF8zj67urNwuX-5xSGqWgM,1762
40
- uipath/_cli/_dev/_terminal/_styles/terminal.tcss,sha256=k455ZxeB54hzPyH3CAj8VNLUtQPCCHr0IbTU1mqhD3U,5012
41
+ uipath/_cli/_dev/_terminal/_styles/terminal.tcss,sha256=C4XMJJtEzKSqanh9GU-fgGye3uexYvnjNG4jdKnRslI,2591
41
42
  uipath/_cli/_dev/_terminal/_traces/_exporter.py,sha256=oI6D_eMwrh_2aqDYUh4GrJg8VLGrLYhDahR-_o0uJns,4144
42
43
  uipath/_cli/_dev/_terminal/_traces/_logger.py,sha256=Dmfba3X9GmAZtXpzu_KDsleRCrpVo8_y-W6jizwFYq0,880
43
44
  uipath/_cli/_evals/evaluation_service.py,sha256=zqYRB-tZpTTFqMctjIpEli3joIlmrz3dCVZsxekxIps,22053
@@ -58,7 +59,7 @@ uipath/_cli/_runtime/_contracts.py,sha256=ays9ki4PQjdiy_z_kuR_Z0mHYVy_MZ6DvBG6g_
58
59
  uipath/_cli/_runtime/_escalation.py,sha256=x3vI98qsfRA-fL_tNkRVTFXioM5Gv2w0GFcXJJ5eQtg,7981
59
60
  uipath/_cli/_runtime/_hitl.py,sha256=aexwe0dIXvh6SlVS1jVnO_aGZc6e3gLsmGkCyha5AHo,11300
60
61
  uipath/_cli/_runtime/_logging.py,sha256=MGklGKPjYKjs7J5Jy9eplA9zCDsdtEbkZdCbTwgut_4,8311
61
- uipath/_cli/_runtime/_runtime.py,sha256=tgoMYALRTMGL8pSYbSL5nXJfq0lf_RGuNc7fmS4dlf4,11419
62
+ uipath/_cli/_runtime/_runtime.py,sha256=TXtXzscRPLdYJURH0Y-7sXsigC-2k_LttBOz7EUfWUQ,11449
62
63
  uipath/_cli/_templates/.psmdcp.template,sha256=C7pBJPt98ovEljcBvGtEUGoWjjQhu9jls1bpYjeLOKA,611
63
64
  uipath/_cli/_templates/.rels.template,sha256=-fTcw7OA1AcymHr0LzBqbMAAtzZTRXLTNa_ljq087Jk,406
64
65
  uipath/_cli/_templates/[Content_Types].xml.template,sha256=bYsKDz31PkIF9QksjgAY_bqm57YC8U_owsZeNZAiBxQ,584
@@ -126,8 +127,8 @@ uipath/tracing/_traced.py,sha256=qeVDrds2OUnpdUIA0RhtF0kg2dlAZhyC1RRkI-qivTM,185
126
127
  uipath/tracing/_utils.py,sha256=wJRELaPu69iY0AhV432Dk5QYf_N_ViRU4kAUG1BI1ew,10384
127
128
  uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
128
129
  uipath/utils/_endpoints_manager.py,sha256=iRTl5Q0XAm_YgcnMcJOXtj-8052sr6jpWuPNz6CgT0Q,8408
129
- uipath-2.1.30.dist-info/METADATA,sha256=cdYoQSTtuOZwpUqBNnllIyY0sZ5sdI6upc7x9X7a8RM,6450
130
- uipath-2.1.30.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
131
- uipath-2.1.30.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
132
- uipath-2.1.30.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
133
- uipath-2.1.30.dist-info/RECORD,,
130
+ uipath-2.1.32.dist-info/METADATA,sha256=ouBZDro2TME5ykTsNMJoN3_qiI1wDHt_Ys7nCZF8z8A,6450
131
+ uipath-2.1.32.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
132
+ uipath-2.1.32.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
133
+ uipath-2.1.32.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
134
+ uipath-2.1.32.dist-info/RECORD,,