uipath 2.1.88__py3-none-any.whl → 2.1.89__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.
Potentially problematic release.
This version of uipath might be problematic. Click here for more details.
- uipath/_cli/_evals/_models/_evaluation_set.py +13 -0
- uipath/_cli/_evals/_runtime.py +18 -0
- uipath/_cli/_evals/mocks/input_mocker.py +111 -0
- uipath/_cli/_evals/mocks/mocker.py +6 -0
- uipath/_cli/_push/sw_file_handler.py +24 -40
- uipath/_cli/_runtime/_logging.py +4 -0
- uipath/_cli/_utils/_project_files.py +67 -37
- uipath/_cli/cli_pull.py +22 -1
- uipath/agent/_utils.py +14 -1
- uipath/agent/loop/__init__.py +17 -0
- uipath/agent/loop/prompts.py +57 -0
- uipath/agent/loop/tools.py +42 -0
- {uipath-2.1.88.dist-info → uipath-2.1.89.dist-info}/METADATA +1 -1
- {uipath-2.1.88.dist-info → uipath-2.1.89.dist-info}/RECORD +17 -13
- {uipath-2.1.88.dist-info → uipath-2.1.89.dist-info}/WHEEL +0 -0
- {uipath-2.1.88.dist-info → uipath-2.1.89.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.88.dist-info → uipath-2.1.89.dist-info}/licenses/LICENSE +0 -0
|
@@ -44,6 +44,15 @@ class LLMMockingStrategy(BaseMockingStrategy):
|
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
class InputMockingStrategy(BaseModel):
|
|
48
|
+
prompt: str = Field(..., alias="prompt")
|
|
49
|
+
model: Optional[ModelSettings] = Field(None, alias="model")
|
|
50
|
+
|
|
51
|
+
model_config = ConfigDict(
|
|
52
|
+
validate_by_name=True, validate_by_alias=True, extra="allow"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
47
56
|
class MockingArgument(BaseModel):
|
|
48
57
|
args: List[Any] = Field(default_factory=lambda: [], alias="args")
|
|
49
58
|
kwargs: Dict[str, Any] = Field(default_factory=lambda: {}, alias="kwargs")
|
|
@@ -110,6 +119,10 @@ class EvaluationItem(BaseModel):
|
|
|
110
119
|
default=None,
|
|
111
120
|
alias="mockingStrategy",
|
|
112
121
|
)
|
|
122
|
+
input_mocking_strategy: Optional[InputMockingStrategy] = Field(
|
|
123
|
+
default=None,
|
|
124
|
+
alias="inputMockingStrategy",
|
|
125
|
+
)
|
|
113
126
|
|
|
114
127
|
|
|
115
128
|
class EvaluationSet(BaseModel):
|
uipath/_cli/_evals/_runtime.py
CHANGED
|
@@ -11,6 +11,10 @@ from opentelemetry import context as context_api
|
|
|
11
11
|
from opentelemetry.sdk.trace import ReadableSpan, Span
|
|
12
12
|
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
|
13
13
|
|
|
14
|
+
from uipath._cli._evals.mocks.input_mocker import (
|
|
15
|
+
generate_llm_input,
|
|
16
|
+
)
|
|
17
|
+
|
|
14
18
|
from ..._events._event_bus import EventBus
|
|
15
19
|
from ..._events._events import (
|
|
16
20
|
EvalItemExceptionDetails,
|
|
@@ -318,6 +322,10 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
|
318
322
|
evaluators: List[BaseEvaluator[Any]],
|
|
319
323
|
event_bus: EventBus,
|
|
320
324
|
) -> EvaluationRunResult:
|
|
325
|
+
# Generate LLM-based input if input_mocking_strategy is defined
|
|
326
|
+
if eval_item.input_mocking_strategy:
|
|
327
|
+
eval_item = await self._generate_input_for_eval(eval_item)
|
|
328
|
+
|
|
321
329
|
set_execution_context(eval_item, self.span_collector)
|
|
322
330
|
|
|
323
331
|
await event_bus.publish(
|
|
@@ -417,6 +425,16 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
|
417
425
|
|
|
418
426
|
return evaluation_run_results
|
|
419
427
|
|
|
428
|
+
async def _generate_input_for_eval(
|
|
429
|
+
self, eval_item: EvaluationItem
|
|
430
|
+
) -> EvaluationItem:
|
|
431
|
+
"""Use LLM to generate a mock input for an evaluation item."""
|
|
432
|
+
# TODO(bai): get the input schema from agent definition, once it is available there.
|
|
433
|
+
input_schema: dict[str, Any] = {}
|
|
434
|
+
generated_input = await generate_llm_input(eval_item, input_schema)
|
|
435
|
+
updated_eval_item = eval_item.model_copy(update={"inputs": generated_input})
|
|
436
|
+
return updated_eval_item
|
|
437
|
+
|
|
420
438
|
def _get_and_clear_execution_data(
|
|
421
439
|
self, execution_id: str
|
|
422
440
|
) -> tuple[List[ReadableSpan], list[logging.LogRecord]]:
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""LLM Input Mocker implementation."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict
|
|
6
|
+
|
|
7
|
+
from uipath import UiPath
|
|
8
|
+
from uipath._cli._evals._models._evaluation_set import EvaluationItem
|
|
9
|
+
from uipath.tracing._traced import traced
|
|
10
|
+
|
|
11
|
+
from .mocker import UiPathInputMockingError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_input_mocking_prompt(
|
|
15
|
+
input_schema: str,
|
|
16
|
+
input_generation_instructions: str,
|
|
17
|
+
expected_behavior: str,
|
|
18
|
+
expected_output: str,
|
|
19
|
+
) -> str:
|
|
20
|
+
"""Generate the LLM input mocking prompt."""
|
|
21
|
+
current_datetime = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
|
|
22
|
+
|
|
23
|
+
return f"""You are simulating input for automated testing purposes of an Agent as part of a simulation run.
|
|
24
|
+
You will need to generate realistic input to a LLM agent which will call various tools to achieve a goal. This must be in the exact format of the INPUT_SCHEMA.
|
|
25
|
+
You may need to follow specific INPUT_GENERATION_INSTRUCTIONS. If no relevant instructions are provided pertaining to input generation, use the other provided information and your own judgement to generate input.
|
|
26
|
+
If the INPUT_GENERATION_INSTRUCTIONS are provided, you MUST follow them exactly. For example if the instructions say to generate a value for a field to be before a certain calendar date, you must generate a value that is before that date.
|
|
27
|
+
|
|
28
|
+
The current date and time is: {current_datetime}
|
|
29
|
+
|
|
30
|
+
#INPUT_SCHEMA: You MUST OUTPUT THIS EXACT JSON SCHEMA
|
|
31
|
+
{input_schema}
|
|
32
|
+
#END_INPUT_SCHEMA
|
|
33
|
+
|
|
34
|
+
#INPUT_GENERATION_INSTRUCTIONS
|
|
35
|
+
{input_generation_instructions}
|
|
36
|
+
#END_INPUT_GENERATION_INSTRUCTIONS
|
|
37
|
+
|
|
38
|
+
#EXPECTED_BEHAVIOR
|
|
39
|
+
{expected_behavior}
|
|
40
|
+
#END_EXPECTED_BEHAVIOR
|
|
41
|
+
|
|
42
|
+
#EXPECTED_OUTPUT
|
|
43
|
+
{expected_output}
|
|
44
|
+
#END_EXPECTED_OUTPUT
|
|
45
|
+
|
|
46
|
+
Based on the above information, provide a realistic input to the LLM agent. Your response should:
|
|
47
|
+
1. Match the expected input format according to the INPUT_SCHEMA exactly
|
|
48
|
+
2. Be consistent with the style and level of detail in the example inputs
|
|
49
|
+
3. Consider the context of the the agent being tested
|
|
50
|
+
4. Be realistic and representative of what a real user might say or ask
|
|
51
|
+
|
|
52
|
+
OUTPUT: ONLY the simulated agent input in the exact format of the INPUT_SCHEMA in valid JSON. Do not include any explanations, quotation marks, or markdown."""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@traced(name="__mocker__")
|
|
56
|
+
async def generate_llm_input(
|
|
57
|
+
evaluation_item: EvaluationItem,
|
|
58
|
+
input_schema: Dict[str, Any],
|
|
59
|
+
) -> Dict[str, Any]:
|
|
60
|
+
"""Generate synthetic input using an LLM based on the evaluation context."""
|
|
61
|
+
try:
|
|
62
|
+
llm = UiPath().llm
|
|
63
|
+
|
|
64
|
+
prompt = get_input_mocking_prompt(
|
|
65
|
+
input_schema=json.dumps(input_schema, indent=2),
|
|
66
|
+
input_generation_instructions=evaluation_item.input_mocking_strategy.prompt
|
|
67
|
+
if evaluation_item.input_mocking_strategy
|
|
68
|
+
else "",
|
|
69
|
+
expected_behavior=evaluation_item.expected_agent_behavior or "",
|
|
70
|
+
expected_output=json.dumps(evaluation_item.expected_output, indent=2)
|
|
71
|
+
if evaluation_item.expected_output
|
|
72
|
+
else "",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
response_format = {
|
|
76
|
+
"type": "json_schema",
|
|
77
|
+
"json_schema": {
|
|
78
|
+
"name": "agent_input",
|
|
79
|
+
"strict": True,
|
|
80
|
+
"schema": input_schema,
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
model_parameters = (
|
|
85
|
+
evaluation_item.input_mocking_strategy.model
|
|
86
|
+
if evaluation_item.input_mocking_strategy
|
|
87
|
+
else None
|
|
88
|
+
)
|
|
89
|
+
completion_kwargs = (
|
|
90
|
+
model_parameters.model_dump(by_alias=False, exclude_none=True)
|
|
91
|
+
if model_parameters
|
|
92
|
+
else {}
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
response = await llm.chat_completions(
|
|
96
|
+
[{"role": "user", "content": prompt}],
|
|
97
|
+
response_format=response_format,
|
|
98
|
+
**completion_kwargs,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
generated_input_str = response.choices[0].message.content
|
|
102
|
+
|
|
103
|
+
return json.loads(generated_input_str)
|
|
104
|
+
except json.JSONDecodeError as e:
|
|
105
|
+
raise UiPathInputMockingError(
|
|
106
|
+
f"Failed to parse LLM response as JSON: {str(e)}"
|
|
107
|
+
) from e
|
|
108
|
+
except UiPathInputMockingError:
|
|
109
|
+
raise
|
|
110
|
+
except Exception as e:
|
|
111
|
+
raise UiPathInputMockingError(f"Failed to generate input: {str(e)}") from e
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"""Studio Web File Handler for managing file operations in UiPath projects."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import logging
|
|
4
5
|
import os
|
|
5
6
|
from datetime import datetime, timezone
|
|
6
7
|
from typing import Any, Dict, Optional, Set
|
|
7
8
|
|
|
8
|
-
import click
|
|
9
|
-
|
|
10
9
|
from ...models.exceptions import EnrichedException
|
|
11
|
-
from .._utils._console import ConsoleLogger
|
|
12
10
|
from .._utils._constants import (
|
|
13
11
|
AGENT_INITIAL_CODE_VERSION,
|
|
14
12
|
AGENT_STORAGE_VERSION,
|
|
@@ -30,6 +28,8 @@ from .._utils._studio_project import (
|
|
|
30
28
|
StudioClient,
|
|
31
29
|
)
|
|
32
30
|
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
33
|
|
|
34
34
|
class SwFileHandler:
|
|
35
35
|
"""Handler for Studio Web file operations.
|
|
@@ -58,7 +58,6 @@ class SwFileHandler:
|
|
|
58
58
|
"""
|
|
59
59
|
self.directory = directory
|
|
60
60
|
self.include_uv_lock = include_uv_lock
|
|
61
|
-
self.console = ConsoleLogger()
|
|
62
61
|
self._studio_client = StudioClient(project_id)
|
|
63
62
|
self._project_structure: Optional[ProjectStructure] = None
|
|
64
63
|
|
|
@@ -156,9 +155,7 @@ class SwFileHandler:
|
|
|
156
155
|
|
|
157
156
|
for local_file in local_files:
|
|
158
157
|
if not os.path.exists(local_file.file_path):
|
|
159
|
-
|
|
160
|
-
f"File not found: {click.style(local_file.file_path, fg='cyan')}"
|
|
161
|
-
)
|
|
158
|
+
logger.info(f"File not found: '{local_file.file_path}'")
|
|
162
159
|
continue
|
|
163
160
|
|
|
164
161
|
# Skip agent.json as it's handled separately
|
|
@@ -175,9 +172,7 @@ class SwFileHandler:
|
|
|
175
172
|
id=remote_file.id, content_file_path=local_file.file_path
|
|
176
173
|
)
|
|
177
174
|
)
|
|
178
|
-
|
|
179
|
-
f"Updating {click.style(local_file.file_name, fg='yellow')}"
|
|
180
|
-
)
|
|
175
|
+
logger.info(f"Updating '{local_file.file_name}'")
|
|
181
176
|
else:
|
|
182
177
|
parent_path = os.path.dirname(local_file.relative_path)
|
|
183
178
|
structural_migration.added_resources.append(
|
|
@@ -188,9 +183,7 @@ class SwFileHandler:
|
|
|
188
183
|
else "source_code",
|
|
189
184
|
)
|
|
190
185
|
)
|
|
191
|
-
|
|
192
|
-
f"Uploading {click.style(local_file.relative_path, fg='cyan')}"
|
|
193
|
-
)
|
|
186
|
+
logger.info(f"Uploading '{local_file.relative_path}'")
|
|
194
187
|
|
|
195
188
|
# identify and add deleted files
|
|
196
189
|
structural_migration.deleted_resources.extend(
|
|
@@ -236,9 +229,7 @@ class SwFileHandler:
|
|
|
236
229
|
for _, remote_file in source_code_files.items():
|
|
237
230
|
if remote_file.id not in processed_source_file_paths:
|
|
238
231
|
deleted_files.add(remote_file.id)
|
|
239
|
-
|
|
240
|
-
f"Deleting {click.style(remote_file.name, fg='bright_red')}"
|
|
241
|
-
)
|
|
232
|
+
logger.info(f"Deleting '{remote_file.name}'")
|
|
242
233
|
|
|
243
234
|
return deleted_files
|
|
244
235
|
|
|
@@ -263,16 +254,14 @@ class SwFileHandler:
|
|
|
263
254
|
for folder_info in empty_folder_ids:
|
|
264
255
|
try:
|
|
265
256
|
await self._studio_client.delete_item_async(folder_info["id"])
|
|
266
|
-
|
|
267
|
-
f"Deleted empty folder {click.style(folder_info['name'], fg='bright_red')}"
|
|
268
|
-
)
|
|
257
|
+
logger.info(f"Deleted empty folder '{folder_info['name']}'")
|
|
269
258
|
except Exception as e:
|
|
270
|
-
|
|
271
|
-
f"Failed to delete empty folder {folder_info['name']}: {str(e)}"
|
|
259
|
+
logger.warning(
|
|
260
|
+
f"Failed to delete empty folder '{folder_info['name']}': {str(e)}"
|
|
272
261
|
)
|
|
273
262
|
|
|
274
263
|
except Exception as e:
|
|
275
|
-
|
|
264
|
+
logger.warning(f"Failed to cleanup empty folders: {str(e)}")
|
|
276
265
|
|
|
277
266
|
def _collect_empty_folders(self, folder: ProjectFolder) -> list[dict[str, str]]:
|
|
278
267
|
"""Recursively collect IDs and names of empty folders.
|
|
@@ -335,8 +324,8 @@ class SwFileHandler:
|
|
|
335
324
|
entry_points_json["entryPoints"] = uipath_config["entryPoints"]
|
|
336
325
|
|
|
337
326
|
except Exception:
|
|
338
|
-
|
|
339
|
-
"Could not parse existing entry-points.json file, using default version"
|
|
327
|
+
logger.info(
|
|
328
|
+
"Could not parse existing 'entry-points.json' file, using default version"
|
|
340
329
|
)
|
|
341
330
|
structural_migration.modified_resources.append(
|
|
342
331
|
ModifiedResource(
|
|
@@ -344,12 +333,10 @@ class SwFileHandler:
|
|
|
344
333
|
content_string=json.dumps(entry_points_json),
|
|
345
334
|
)
|
|
346
335
|
)
|
|
347
|
-
|
|
348
|
-
f"Updating {click.style('entry-points.json', fg='yellow')}"
|
|
349
|
-
)
|
|
336
|
+
logger.info("Updating 'entry-points.json'")
|
|
350
337
|
|
|
351
338
|
else:
|
|
352
|
-
|
|
339
|
+
logger.info(
|
|
353
340
|
"'entry-points.json' file does not exist in Studio Web project, initializing using default version"
|
|
354
341
|
)
|
|
355
342
|
entry_points_json = {
|
|
@@ -363,9 +350,7 @@ class SwFileHandler:
|
|
|
363
350
|
content_string=json.dumps(entry_points_json),
|
|
364
351
|
)
|
|
365
352
|
)
|
|
366
|
-
|
|
367
|
-
f"Uploading {click.style('entry-points.json', fg='cyan')}"
|
|
368
|
-
)
|
|
353
|
+
logger.info("Uploading 'entry-points.json'")
|
|
369
354
|
|
|
370
355
|
async def _prepare_agent_json_migration(
|
|
371
356
|
self,
|
|
@@ -400,9 +385,10 @@ class SwFileHandler:
|
|
|
400
385
|
input_schema = uipath_config["entryPoints"][0]["input"]
|
|
401
386
|
output_schema = uipath_config["entryPoints"][0]["output"]
|
|
402
387
|
except (FileNotFoundError, KeyError) as e:
|
|
403
|
-
|
|
388
|
+
logger.error(
|
|
404
389
|
f"Unable to extract entrypoints from configuration file. Please run 'uipath init' : {str(e)}",
|
|
405
390
|
)
|
|
391
|
+
return
|
|
406
392
|
|
|
407
393
|
author = get_author_from_token_or_toml()
|
|
408
394
|
|
|
@@ -444,8 +430,8 @@ class SwFileHandler:
|
|
|
444
430
|
AGENT_INITIAL_CODE_VERSION[:-1] + "1"
|
|
445
431
|
)
|
|
446
432
|
except Exception:
|
|
447
|
-
|
|
448
|
-
"Could not parse existing agent.json file, using default version"
|
|
433
|
+
logger.info(
|
|
434
|
+
"Could not parse existing 'agent.json' file, using default version"
|
|
449
435
|
)
|
|
450
436
|
|
|
451
437
|
structural_migration.modified_resources.append(
|
|
@@ -454,9 +440,9 @@ class SwFileHandler:
|
|
|
454
440
|
content_string=json.dumps(agent_json),
|
|
455
441
|
)
|
|
456
442
|
)
|
|
457
|
-
|
|
443
|
+
logger.info("Updating 'agent.json'")
|
|
458
444
|
else:
|
|
459
|
-
|
|
445
|
+
logger.info(
|
|
460
446
|
"'agent.json' file does not exist in Studio Web project, initializing using default version"
|
|
461
447
|
)
|
|
462
448
|
structural_migration.added_resources.append(
|
|
@@ -465,7 +451,7 @@ class SwFileHandler:
|
|
|
465
451
|
content_string=json.dumps(agent_json),
|
|
466
452
|
)
|
|
467
453
|
)
|
|
468
|
-
|
|
454
|
+
logger.info("Uploading 'agent.json'")
|
|
469
455
|
|
|
470
456
|
async def upload_source_files(self, config_data: dict[str, Any]) -> None:
|
|
471
457
|
"""Main method to upload source files to the UiPath project.
|
|
@@ -502,9 +488,7 @@ class SwFileHandler:
|
|
|
502
488
|
if not source_code_folder:
|
|
503
489
|
await self._studio_client.create_folder_async("source_code")
|
|
504
490
|
|
|
505
|
-
|
|
506
|
-
f"Created {click.style('source_code', fg='cyan')} folder"
|
|
507
|
-
)
|
|
491
|
+
logger.info("Created 'source_code' folder.")
|
|
508
492
|
source_code_files = {}
|
|
509
493
|
|
|
510
494
|
# Get files to upload and process them
|
uipath/_cli/_runtime/_logging.py
CHANGED
|
@@ -266,6 +266,10 @@ class LogsInterceptor:
|
|
|
266
266
|
def writable(self) -> bool:
|
|
267
267
|
return True
|
|
268
268
|
|
|
269
|
+
def __getattr__(self, name):
|
|
270
|
+
# Delegate any unknown attributes to the original file
|
|
271
|
+
return getattr(self.sys_file, name)
|
|
272
|
+
|
|
269
273
|
# Set up stdout and stderr loggers
|
|
270
274
|
stdout_logger = logging.getLogger("stdout")
|
|
271
275
|
stderr_logger = logging.getLogger("stderr")
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# type: ignore
|
|
2
2
|
import hashlib
|
|
3
3
|
import json
|
|
4
|
+
import logging
|
|
4
5
|
import os
|
|
5
6
|
import re
|
|
6
7
|
from pathlib import Path
|
|
7
|
-
from typing import Any, Dict, Optional, Tuple
|
|
8
|
+
from typing import Any, Dict, Optional, Protocol, Tuple
|
|
8
9
|
|
|
9
|
-
import click
|
|
10
10
|
from pydantic import BaseModel
|
|
11
11
|
|
|
12
12
|
from .._utils._console import ConsoleLogger
|
|
@@ -22,6 +22,35 @@ try:
|
|
|
22
22
|
import tomllib
|
|
23
23
|
except ImportError:
|
|
24
24
|
import tomli as tomllib
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FileConflictHandler(Protocol):
|
|
29
|
+
"""Protocol for handling file conflicts."""
|
|
30
|
+
|
|
31
|
+
def should_overwrite(
|
|
32
|
+
self, file_path: str, local_hash: str, remote_hash: str
|
|
33
|
+
) -> bool:
|
|
34
|
+
"""Return True to overwrite, False to skip."""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AlwaysOverwriteHandler:
|
|
39
|
+
"""Handler that always overwrites files."""
|
|
40
|
+
|
|
41
|
+
def should_overwrite(
|
|
42
|
+
self, file_path: str, local_hash: str, remote_hash: str
|
|
43
|
+
) -> bool:
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class AlwaysSkipHandler:
|
|
48
|
+
"""Handler that always skips conflicts."""
|
|
49
|
+
|
|
50
|
+
def should_overwrite(
|
|
51
|
+
self, file_path: str, local_hash: str, remote_hash: str
|
|
52
|
+
) -> bool:
|
|
53
|
+
return False
|
|
25
54
|
|
|
26
55
|
|
|
27
56
|
class FileInfo(BaseModel):
|
|
@@ -483,10 +512,37 @@ def collect_files_from_folder(
|
|
|
483
512
|
collect_files_from_folder(subfolder, subfolder_path, files_dict)
|
|
484
513
|
|
|
485
514
|
|
|
515
|
+
async def pull_project(
|
|
516
|
+
project_id: str,
|
|
517
|
+
download_configuration: dict[str, Path],
|
|
518
|
+
conflict_handler: Optional[FileConflictHandler] = None,
|
|
519
|
+
):
|
|
520
|
+
"""Pull project with configurable conflict handling."""
|
|
521
|
+
if conflict_handler is None:
|
|
522
|
+
conflict_handler = AlwaysOverwriteHandler()
|
|
523
|
+
|
|
524
|
+
studio_client = StudioClient(project_id)
|
|
525
|
+
|
|
526
|
+
try:
|
|
527
|
+
structure = await studio_client.get_project_structure_async()
|
|
528
|
+
for source_key, destination in download_configuration.items():
|
|
529
|
+
source_folder = get_folder_by_name(structure, source_key)
|
|
530
|
+
if source_folder:
|
|
531
|
+
await download_folder_files(
|
|
532
|
+
studio_client, source_folder, destination, conflict_handler
|
|
533
|
+
)
|
|
534
|
+
else:
|
|
535
|
+
logger.warning(f"No '{source_key}' folder found in remote project")
|
|
536
|
+
except Exception:
|
|
537
|
+
logger.exception("Failed to pull UiPath project")
|
|
538
|
+
raise
|
|
539
|
+
|
|
540
|
+
|
|
486
541
|
async def download_folder_files(
|
|
487
542
|
studio_client: StudioClient,
|
|
488
543
|
folder: ProjectFolder,
|
|
489
544
|
base_path: Path,
|
|
545
|
+
conflict_handler: FileConflictHandler,
|
|
490
546
|
) -> None:
|
|
491
547
|
"""Download files from a folder recursively.
|
|
492
548
|
|
|
@@ -494,62 +550,36 @@ async def download_folder_files(
|
|
|
494
550
|
studio_client: Studio client
|
|
495
551
|
folder: The folder to download files from
|
|
496
552
|
base_path: Base path for local file storage
|
|
553
|
+
conflict_handler: Handler for file conflicts
|
|
497
554
|
"""
|
|
498
555
|
files_dict: Dict[str, ProjectFile] = {}
|
|
499
556
|
collect_files_from_folder(folder, "", files_dict)
|
|
557
|
+
|
|
500
558
|
for file_path, remote_file in files_dict.items():
|
|
501
559
|
local_path = base_path / file_path
|
|
502
560
|
local_path.parent.mkdir(parents=True, exist_ok=True)
|
|
503
561
|
|
|
504
|
-
# Download remote file
|
|
505
562
|
response = await studio_client.download_file_async(remote_file.id)
|
|
506
563
|
remote_content = response.read().decode("utf-8")
|
|
507
564
|
remote_hash = compute_normalized_hash(remote_content)
|
|
508
565
|
|
|
509
566
|
if os.path.exists(local_path):
|
|
510
|
-
# Read and hash local file
|
|
511
567
|
with open(local_path, "r", encoding="utf-8") as f:
|
|
512
568
|
local_content = f.read()
|
|
513
569
|
local_hash = compute_normalized_hash(local_content)
|
|
514
570
|
|
|
515
|
-
# Compare hashes
|
|
516
571
|
if local_hash != remote_hash:
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
if response.lower() == "y":
|
|
572
|
+
if conflict_handler.should_overwrite(
|
|
573
|
+
file_path, local_hash, remote_hash
|
|
574
|
+
):
|
|
521
575
|
with open(local_path, "w", encoding="utf-8", newline="\n") as f:
|
|
522
576
|
f.write(remote_content)
|
|
523
|
-
|
|
577
|
+
logger.info(f"Updated '{file_path}'")
|
|
524
578
|
else:
|
|
525
|
-
|
|
579
|
+
logger.info(f"Skipped '{file_path}'")
|
|
526
580
|
else:
|
|
527
|
-
|
|
528
|
-
f"File {click.style(str(file_path), fg='cyan')} is up to date"
|
|
529
|
-
)
|
|
581
|
+
logger.info(f"File '{file_path}' is up to date")
|
|
530
582
|
else:
|
|
531
|
-
# File doesn't exist locally, create it
|
|
532
583
|
with open(local_path, "w", encoding="utf-8", newline="\n") as f:
|
|
533
584
|
f.write(remote_content)
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
async def pull_project(project_id: str, download_configuration: dict[str, Path]):
|
|
538
|
-
studio_client = StudioClient(project_id)
|
|
539
|
-
|
|
540
|
-
with console.spinner("Pulling UiPath project files..."):
|
|
541
|
-
try:
|
|
542
|
-
structure = await studio_client.get_project_structure_async()
|
|
543
|
-
for source_key, destination in download_configuration.items():
|
|
544
|
-
source_folder = get_folder_by_name(structure, source_key)
|
|
545
|
-
if source_folder:
|
|
546
|
-
await download_folder_files(
|
|
547
|
-
studio_client,
|
|
548
|
-
source_folder,
|
|
549
|
-
destination,
|
|
550
|
-
)
|
|
551
|
-
else:
|
|
552
|
-
console.warning(f"No {source_key} folder found in remote project")
|
|
553
|
-
|
|
554
|
-
except Exception as e:
|
|
555
|
-
console.error(f"Failed to pull UiPath project: {str(e)}")
|
|
585
|
+
logger.info(f"Downloaded '{file_path}'")
|
uipath/_cli/cli_pull.py
CHANGED
|
@@ -24,6 +24,20 @@ from ._utils._project_files import pull_project
|
|
|
24
24
|
console = ConsoleLogger()
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
class InteractiveConflictHandler:
|
|
28
|
+
"""Handler that prompts user for each conflict."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, console: ConsoleLogger):
|
|
31
|
+
self.console = console
|
|
32
|
+
|
|
33
|
+
def should_overwrite(
|
|
34
|
+
self, file_path: str, local_hash: str, remote_hash: str
|
|
35
|
+
) -> bool:
|
|
36
|
+
self.console.warning(f" File {file_path} differs from remote version.")
|
|
37
|
+
response = click.confirm("Do you want to overwrite it?", default=False)
|
|
38
|
+
return response
|
|
39
|
+
|
|
40
|
+
|
|
27
41
|
@click.command()
|
|
28
42
|
@click.argument(
|
|
29
43
|
"root",
|
|
@@ -56,4 +70,11 @@ def pull(root: Path) -> None:
|
|
|
56
70
|
"source_code": root,
|
|
57
71
|
"evals": root / "evals",
|
|
58
72
|
}
|
|
59
|
-
|
|
73
|
+
with console.spinner("Pulling UiPath project files..."):
|
|
74
|
+
asyncio.run(
|
|
75
|
+
pull_project(
|
|
76
|
+
project_id,
|
|
77
|
+
default_download_configuration,
|
|
78
|
+
InteractiveConflictHandler(console),
|
|
79
|
+
)
|
|
80
|
+
)
|
uipath/agent/_utils.py
CHANGED
|
@@ -4,7 +4,10 @@ from pathlib import PurePath
|
|
|
4
4
|
from httpx import Response
|
|
5
5
|
from pydantic import TypeAdapter
|
|
6
6
|
|
|
7
|
-
from uipath._cli._evals._models._evaluation_set import
|
|
7
|
+
from uipath._cli._evals._models._evaluation_set import (
|
|
8
|
+
InputMockingStrategy,
|
|
9
|
+
LLMMockingStrategy,
|
|
10
|
+
)
|
|
8
11
|
from uipath._cli._push.sw_file_handler import SwFileHandler
|
|
9
12
|
from uipath._cli._utils._studio_project import (
|
|
10
13
|
ProjectFile,
|
|
@@ -137,4 +140,14 @@ async def load_agent_definition(project_id: str) -> AgentDefinition:
|
|
|
137
140
|
evaluation.mocking_strategy = LLMMockingStrategy(
|
|
138
141
|
prompt=prompt, tools_to_simulate=tools_to_simulate
|
|
139
142
|
)
|
|
143
|
+
|
|
144
|
+
if not evaluation.input_mocking_strategy:
|
|
145
|
+
# Migrate lowCode input mocking fields
|
|
146
|
+
if evaluation.model_extra.get("simulateInput", False):
|
|
147
|
+
prompt = evaluation.model_extra.get(
|
|
148
|
+
"inputGenerationInstructions",
|
|
149
|
+
)
|
|
150
|
+
evaluation.input_mocking_strategy = InputMockingStrategy(
|
|
151
|
+
prompt=prompt
|
|
152
|
+
)
|
|
140
153
|
return agent_definition
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""LowCode Agent Loop Constructs.
|
|
2
|
+
|
|
3
|
+
This module includes agentic loop constructs specific to LowCode Agent
|
|
4
|
+
such as prompts, tools
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from uipath.agent.loop.prompts import AGENT_SYSTEM_PROMPT_TEMPLATE
|
|
8
|
+
from uipath.agent.loop.tools import (
|
|
9
|
+
EndExecutionToolSchemaModel,
|
|
10
|
+
RaiseErrorToolSchemaModel,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"AGENT_SYSTEM_PROMPT_TEMPLATE",
|
|
15
|
+
"EndExecutionToolSchemaModel",
|
|
16
|
+
"RaiseErrorToolSchemaModel",
|
|
17
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""LowCode Agent Prompts."""
|
|
2
|
+
|
|
3
|
+
AGENT_SYSTEM_PROMPT_TEMPLATE = """
|
|
4
|
+
You are an advanced automatic agent equipped with a variety of tools to assist users.
|
|
5
|
+
Your primary function is to understand the user goal and utilize the appropriate tools at your disposal to fulfill it.
|
|
6
|
+
The current date is: {{currentDate}}
|
|
7
|
+
Your name is: {{agentName}}
|
|
8
|
+
|
|
9
|
+
{{systemPrompt}}
|
|
10
|
+
|
|
11
|
+
Your adhere strictly to the following rules to ensure accuracy and data validity:
|
|
12
|
+
|
|
13
|
+
<rules>
|
|
14
|
+
Data Verification and Tool Analysis:
|
|
15
|
+
- **Tool Inspection:** ALWAYS examine tool definitions thoroughly for any pre-configured or hardcoded parameter values before requesting information from the user.
|
|
16
|
+
- **Pre-configured Parameter Usage:** If a parameter is pre-configured or hardcoded, use it directly without asking the user for it.
|
|
17
|
+
- Specificity: Ensure **all information used as tool arguments is concrete and specific**. Utilize values provided in tool definitions when available.
|
|
18
|
+
- Complete tasks accurately or clearly state why it cannot be done. Never proceed with incomplete or invalid information in tool arguments.
|
|
19
|
+
|
|
20
|
+
Tool Usage:
|
|
21
|
+
- **Parameter Resolution:** First check tool definitions for any pre-configured values, then use available context, and only then request missing information from the user.
|
|
22
|
+
- **Preconditions:** Use a tool only when all required parameters have verified, specific data.
|
|
23
|
+
- **Avoid Incomplete Calls:** Do not use tools if any parameter lacks specific data or would require placeholders.
|
|
24
|
+
|
|
25
|
+
Handling Missing Information:
|
|
26
|
+
- **End Execution:** If specific data is missing and no tool is available to obtain it, terminate the process using `end_execution` with a clear reason.
|
|
27
|
+
- **No Placeholder Use:** Do not attempt to use tools with incomplete or placeholder information.
|
|
28
|
+
|
|
29
|
+
Execution Steps:
|
|
30
|
+
- **Step-by-Step Approach:** Break down user requests into required steps and gather necessary information sequentially.
|
|
31
|
+
- **Verification:** Explicitly verify each piece of required information for specificity and validity before proceeding.
|
|
32
|
+
- **Reasoning:** Begin by explaining your reasoning in plain text for each tool call.
|
|
33
|
+
- **Tool Calls:** You can invoke tools, following a logical order where dependent actions occur after their prerequisites.
|
|
34
|
+
- **End execution:** When you have no more steps to perform or you reached a point where you cannot proceed, use the end_execution tool to end the execution.
|
|
35
|
+
</rules>
|
|
36
|
+
|
|
37
|
+
<examples>
|
|
38
|
+
**Example 1: Valid Data Available**
|
|
39
|
+
User Request: "Schedule a meeting with Alice at 10 AM on October 9th 2023."
|
|
40
|
+
Your Response: I will schedule a meeting with Alice at 10 AM on October 9th 2023.
|
|
41
|
+
Tool: schedule_meeting
|
|
42
|
+
Payload: { contact: "Alice", time: "2023-10-09T10:00:00" }
|
|
43
|
+
|
|
44
|
+
**Example 2: Missing Data Without Retrieval Tool:**
|
|
45
|
+
User Request: "Book a flight to Paris."
|
|
46
|
+
Your Response: Cannot proceed because the departure location and date are missing, and no tool is available to obtain this information.
|
|
47
|
+
Tool: raise_error
|
|
48
|
+
Payload: { message: "Missing departure location and date.", details: "Cannot proceed because the departure location and date are missing and no tool is available to obtain this information"}
|
|
49
|
+
|
|
50
|
+
**Example 3: Pre-configured Parameter Usage:**
|
|
51
|
+
User Request: "Retrieve specific details."
|
|
52
|
+
Your Response: I will retrieve the details using the pre-configured parameter value.
|
|
53
|
+
Tool: example_tool
|
|
54
|
+
Payload: { parameterName: "preConfiguredValue" }
|
|
55
|
+
|
|
56
|
+
</examples>
|
|
57
|
+
"""
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""LowCode Agent Tools."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
4
|
+
|
|
5
|
+
TOOL_FLOW_CONTROL_END_EXECUTION = "end_execution"
|
|
6
|
+
TOOL_FLOW_CONTROL_RAISE_ERROR = "raise_error"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EndExecutionToolSchemaModel(BaseModel):
|
|
10
|
+
"""Arguments schema accepted by the `end_execution` control flow tool."""
|
|
11
|
+
|
|
12
|
+
success: bool = Field(
|
|
13
|
+
...,
|
|
14
|
+
description="Whether the execution was successful",
|
|
15
|
+
)
|
|
16
|
+
message: str | None = Field(
|
|
17
|
+
None,
|
|
18
|
+
description="The message to return to the user if the execution was successful",
|
|
19
|
+
)
|
|
20
|
+
error: str | None = Field(
|
|
21
|
+
None,
|
|
22
|
+
description="The error message to return to the user if the execution was unsuccessful",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
model_config = ConfigDict(extra="forbid")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RaiseErrorToolSchemaModel(BaseModel):
|
|
29
|
+
"""Arguments schema accepted by the `raise_error` control flow tool."""
|
|
30
|
+
|
|
31
|
+
message: str = Field(
|
|
32
|
+
...,
|
|
33
|
+
description="The error message to display to the user. This should be a brief one line message.",
|
|
34
|
+
)
|
|
35
|
+
details: str | None = Field(
|
|
36
|
+
None,
|
|
37
|
+
description=(
|
|
38
|
+
"Optional additional details about the error. This can be a multiline text with more details. Only populate this if there are relevant details not already captured in the error message."
|
|
39
|
+
),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
model_config = ConfigDict(extra="forbid")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uipath
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.89
|
|
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
|
|
@@ -15,7 +15,7 @@ uipath/_cli/cli_invoke.py,sha256=m-te-EjhDpk_fhFDkt-yQFzmjEHGo5lQDGEQWxSXisQ,439
|
|
|
15
15
|
uipath/_cli/cli_new.py,sha256=9378NYUBc9j-qKVXV7oja-jahfJhXBg8zKVyaon7ctY,2102
|
|
16
16
|
uipath/_cli/cli_pack.py,sha256=NmwZTfwZ2fURiHyiX1BM0juAtBOjPB1Jmcpu-rD7p-4,11025
|
|
17
17
|
uipath/_cli/cli_publish.py,sha256=DgyfcZjvfV05Ldy0Pk5y_Le_nT9JduEE_x-VpIc_Kq0,6471
|
|
18
|
-
uipath/_cli/cli_pull.py,sha256=
|
|
18
|
+
uipath/_cli/cli_pull.py,sha256=muX2gR-W-bSrNI3pIO0zbhZAP0VBOSsOY2-yrq8HgAw,2433
|
|
19
19
|
uipath/_cli/cli_push.py,sha256=-j-gDIbT8GyU2SybLQqFl5L8KI9nu3CDijVtltDgX20,3132
|
|
20
20
|
uipath/_cli/cli_run.py,sha256=1FKv20EjxrrP1I5rNSnL_HzbWtOAIMjB3M--4RPA_Yo,3709
|
|
21
21
|
uipath/_cli/middlewares.py,sha256=0D9a-wphyetnH9T97F08o7-1OKWF1lMweFHHAR0xiOw,4979
|
|
@@ -46,9 +46,9 @@ uipath/_cli/_dev/_terminal/_utils/_logger.py,sha256=_ipTl_oAiMF9I7keGt2AAFAMz40D
|
|
|
46
46
|
uipath/_cli/_evals/_console_progress_reporter.py,sha256=HgB6pdMyoS6YVwuI3EpM2LBcH3U69nrdaTyNgPG8ssg,9304
|
|
47
47
|
uipath/_cli/_evals/_evaluator_factory.py,sha256=Gycv94VtGOpMir_Gba-UoiAyrSRfbSfe8_pTfjzcA9Q,3875
|
|
48
48
|
uipath/_cli/_evals/_progress_reporter.py,sha256=kX7rNSa-QCLXIzK-vb9Jjf-XLEtucdeiQPgPlSkpp2U,16778
|
|
49
|
-
uipath/_cli/_evals/_runtime.py,sha256=
|
|
49
|
+
uipath/_cli/_evals/_runtime.py,sha256=eK32s4yWOFsiwYBbe5bml02oNarKT6q7bkSalTuoodY,20608
|
|
50
50
|
uipath/_cli/_evals/_span_collection.py,sha256=RoKoeDFG2XODdlgI27ionCjU7LLD_C0LJJ3gu0wab10,779
|
|
51
|
-
uipath/_cli/_evals/_models/_evaluation_set.py,sha256=
|
|
51
|
+
uipath/_cli/_evals/_models/_evaluation_set.py,sha256=0I83I3HNu_BrgFz9miar2QTyXKb0dAaEpYMQrKUHP0U,4958
|
|
52
52
|
uipath/_cli/_evals/_models/_evaluator.py,sha256=fuC3UOYwPD4d_wdynHeLSCzbu82golNAnnPnxC8Y4rk,3315
|
|
53
53
|
uipath/_cli/_evals/_models/_evaluator_base_params.py,sha256=lTYKOV66tcjW85KHTyOdtF1p1VDaBNemrMAvH8bFIFc,382
|
|
54
54
|
uipath/_cli/_evals/_models/_exceptions.py,sha256=-oXLTDa4ab9Boa34ZxuUrCezf8ajIGrIEUVwZnmBASE,195
|
|
@@ -56,16 +56,17 @@ uipath/_cli/_evals/_models/_mocks.py,sha256=mlD9qvdZNniuKxzY_ttJtwLVFvKGvvIukYvy
|
|
|
56
56
|
uipath/_cli/_evals/_models/_output.py,sha256=4KPgXypO2qvWsDf37KbdMGmlYgaIfBSeGgKL32J2nP0,3157
|
|
57
57
|
uipath/_cli/_evals/_models/_sw_reporting.py,sha256=tSBLQFAdOIun8eP0vsqt56K6bmCZz_uMaWI3hskg_24,536
|
|
58
58
|
uipath/_cli/_evals/mocks/__init__.py,sha256=2WXwAy_oZw5bKp6L0HB13QygCJeftOB_Bget0AI6Gik,32
|
|
59
|
+
uipath/_cli/_evals/mocks/input_mocker.py,sha256=imJLriJv1rFthoA-SnJewnNbN27yen8VP11vbv1I9-0,4150
|
|
59
60
|
uipath/_cli/_evals/mocks/llm_mocker.py,sha256=VrjzkeOVAJNKfkrHntQ17MBEtHZhwszEzc_uuPH3Tbc,7355
|
|
60
|
-
uipath/_cli/_evals/mocks/mocker.py,sha256=
|
|
61
|
+
uipath/_cli/_evals/mocks/mocker.py,sha256=VXCxuRAPqUK40kRUXpPmXZRckd7GrOY5ZzIYDe-NNfo,910
|
|
61
62
|
uipath/_cli/_evals/mocks/mocker_factory.py,sha256=V5QKSTtQxztTo4-fK1TyAaXw2Z3mHf2UC5mXqwuUGTs,811
|
|
62
63
|
uipath/_cli/_evals/mocks/mockito_mocker.py,sha256=AO2BmFwA6hz3Lte-STVr7aJDPvMCqKNKa4j2jeNZ_U4,2677
|
|
63
64
|
uipath/_cli/_evals/mocks/mocks.py,sha256=jfenoCSnMPpaXEyAcRDVu5jIfb62eRredRenZDI_AzE,1965
|
|
64
|
-
uipath/_cli/_push/sw_file_handler.py,sha256=
|
|
65
|
+
uipath/_cli/_push/sw_file_handler.py,sha256=gySENzKMcIDtE4u_MrXDK0g-h9wRz6jaJJht1LW54Nc,17877
|
|
65
66
|
uipath/_cli/_runtime/_contracts.py,sha256=E8Is7EQfAu7_hCbeZI68gmTxSxo4X7_U4vcSl7D3Syg,28988
|
|
66
67
|
uipath/_cli/_runtime/_escalation.py,sha256=x3vI98qsfRA-fL_tNkRVTFXioM5Gv2w0GFcXJJ5eQtg,7981
|
|
67
68
|
uipath/_cli/_runtime/_hitl.py,sha256=VKbM021nVg1HEDnTfucSLJ0LsDn83CKyUtVzofS2qTU,11369
|
|
68
|
-
uipath/_cli/_runtime/_logging.py,sha256=
|
|
69
|
+
uipath/_cli/_runtime/_logging.py,sha256=srjAi3Cy6g7b8WNHiYNjaZT4t40F3XRqquuoGd2kh4Y,14019
|
|
69
70
|
uipath/_cli/_runtime/_runtime.py,sha256=P77YtxylLzpK2yz4S0tsBTVFpBSoh5lA7Gpu0SFRD5w,2379
|
|
70
71
|
uipath/_cli/_runtime/_script_executor.py,sha256=PjbmEbyCMofGH2F85b8RFsxdV3Tqw0kVqdWOOk2ZLlI,9687
|
|
71
72
|
uipath/_cli/_templates/.psmdcp.template,sha256=C7pBJPt98ovEljcBvGtEUGoWjjQhu9jls1bpYjeLOKA,611
|
|
@@ -82,7 +83,7 @@ uipath/_cli/_utils/_folders.py,sha256=RsYrXzF0NA1sPxgBoLkLlUY3jDNLg1V-Y8j71Q8a8H
|
|
|
82
83
|
uipath/_cli/_utils/_input_args.py,sha256=AnbQ12D2ACIQFt0QHMaWleRn1ZgRTXuTSTN0ozJiSQg,5766
|
|
83
84
|
uipath/_cli/_utils/_parse_ast.py,sha256=8Iohz58s6bYQ7rgWtOTjrEInLJ-ETikmOMZzZdIY2Co,20072
|
|
84
85
|
uipath/_cli/_utils/_processes.py,sha256=q7DfEKHISDWf3pngci5za_z0Pbnf_shWiYEcTOTCiyk,1855
|
|
85
|
-
uipath/_cli/_utils/_project_files.py,sha256=
|
|
86
|
+
uipath/_cli/_utils/_project_files.py,sha256=ueDUGQrig5EFSgEXUiaXmMGAgs1b_tX2yBpgaXsHcrA,20093
|
|
86
87
|
uipath/_cli/_utils/_studio_project.py,sha256=8WYwi_CiTPRqo8KV2bsvj0H_KBFxTEN0Q2cXoZb-NnM,17030
|
|
87
88
|
uipath/_cli/_utils/_tracing.py,sha256=2igb03j3EHjF_A406UhtCKkPfudVfFPjUq5tXUEG4oo,1541
|
|
88
89
|
uipath/_cli/_utils/_uv_helpers.py,sha256=6SvoLnZPoKIxW0sjMvD1-ENV_HOXDYzH34GjBqwT138,3450
|
|
@@ -123,7 +124,7 @@ uipath/_utils/_ssl_context.py,sha256=xSYitos0eJc9cPHzNtHISX9PBvL6D2vas5G_GiBdLp8
|
|
|
123
124
|
uipath/_utils/_url.py,sha256=-4eluSrIZCUlnQ3qU17WPJkgaC2KwF9W5NeqGnTNGGo,2512
|
|
124
125
|
uipath/_utils/_user_agent.py,sha256=pVJkFYacGwaQBomfwWVAvBQgdBUo62e4n3-fLIajWUU,563
|
|
125
126
|
uipath/_utils/constants.py,sha256=2xLT-1aW0aJS2USeZbK-7zRgyyi1bgV60L0rtQOUqOM,1721
|
|
126
|
-
uipath/agent/_utils.py,sha256=
|
|
127
|
+
uipath/agent/_utils.py,sha256=ec0FJV95pujbMaa0_Vz1nX1fAHp64nJKbf4tYbQn-aI,5560
|
|
127
128
|
uipath/agent/conversation/__init__.py,sha256=5hK-Iz131mnd9m6ANnpZZffxXZLVFDQ9GTg5z9ik1oQ,5265
|
|
128
129
|
uipath/agent/conversation/async_stream.py,sha256=BA_8uU1DgE3VpU2KkJj0rkI3bAHLk_ZJKsajR0ipMpo,2055
|
|
129
130
|
uipath/agent/conversation/citation.py,sha256=42dGv-wiYx3Lt7MPuPCFTkjAlSADFSzjyNXuZHdxqvo,2253
|
|
@@ -134,6 +135,9 @@ uipath/agent/conversation/exchange.py,sha256=nuk1tEMBHc_skrraT17d8U6AtyJ3h07ExGQ
|
|
|
134
135
|
uipath/agent/conversation/message.py,sha256=1ZkEs146s79TrOAWCQwzBAEJvjAu4lQBpJ64tKXDgGE,2142
|
|
135
136
|
uipath/agent/conversation/meta.py,sha256=3t0eS9UHoAPHre97QTUeVbjDhnMX4zj4-qG6ju0B8wY,315
|
|
136
137
|
uipath/agent/conversation/tool.py,sha256=ol8XI8AVd-QNn5auXNBPcCzOkh9PPFtL7hTK3kqInkU,2191
|
|
138
|
+
uipath/agent/loop/__init__.py,sha256=EZlNqrh8xod0VtTJqc-1pyUofaeS6PKjbsDfWoveVtI,424
|
|
139
|
+
uipath/agent/loop/prompts.py,sha256=qPwyd6Ple2m-Kt0m2foa6ZEmxD3kyCXOmGfXvzHi8Rc,3372
|
|
140
|
+
uipath/agent/loop/tools.py,sha256=OsT3x431KqOEzLi2jLxy2B9xXbcFq16xMfmyAqFaqZQ,1351
|
|
137
141
|
uipath/agent/models/agent.py,sha256=18NvqLtuQoEHYnrHiEApWjaka91PYCj_fJRFE72z4Uw,13236
|
|
138
142
|
uipath/eval/_helpers/__init__.py,sha256=GSmZMryjuO3Wo_zdxZdrHCRRsgOxsVFYkYgJ15YNC3E,86
|
|
139
143
|
uipath/eval/_helpers/helpers.py,sha256=iE2HHdMiAdAMLqxHkPKHpfecEtAuN5BTBqvKFTI8ciE,1315
|
|
@@ -177,8 +181,8 @@ uipath/tracing/_utils.py,sha256=X-LFsyIxDeNOGuHPvkb6T5o9Y8ElYhr_rP3CEBJSu4s,1383
|
|
|
177
181
|
uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
|
|
178
182
|
uipath/utils/_endpoints_manager.py,sha256=iRTl5Q0XAm_YgcnMcJOXtj-8052sr6jpWuPNz6CgT0Q,8408
|
|
179
183
|
uipath/utils/dynamic_schema.py,sha256=w0u_54MoeIAB-mf3GmwX1A_X8_HDrRy6p998PvX9evY,3839
|
|
180
|
-
uipath-2.1.
|
|
181
|
-
uipath-2.1.
|
|
182
|
-
uipath-2.1.
|
|
183
|
-
uipath-2.1.
|
|
184
|
-
uipath-2.1.
|
|
184
|
+
uipath-2.1.89.dist-info/METADATA,sha256=n4C3L0fJspBl4pbt_G7qvKkfD_0hdk1AstgioRyE8zg,6593
|
|
185
|
+
uipath-2.1.89.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
186
|
+
uipath-2.1.89.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
|
|
187
|
+
uipath-2.1.89.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
|
|
188
|
+
uipath-2.1.89.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|