uipath 2.0.19.dev1002910038__tar.gz → 2.0.21__tar.gz

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.

Files changed (130) hide show
  1. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/PKG-INFO +2 -2
  2. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/pyproject.toml +2 -2
  3. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/__init__.py +2 -0
  4. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/_auth_server.py +3 -2
  5. uipath-2.0.21/src/uipath/_cli/_utils/_common.py +45 -0
  6. uipath-2.0.21/src/uipath/_cli/_utils/_folders.py +29 -0
  7. uipath-2.0.21/src/uipath/_cli/_utils/_processes.py +49 -0
  8. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/cli_auth.py +25 -15
  9. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/cli_init.py +11 -8
  10. uipath-2.0.21/src/uipath/_cli/cli_invoke.py +105 -0
  11. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/cli_new.py +11 -5
  12. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/cli_pack.py +30 -16
  13. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/cli_publish.py +49 -36
  14. uipath-2.0.21/src/uipath/_cli/spinner.py +40 -0
  15. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/uv.lock +1511 -1746
  16. uipath-2.0.19.dev1002910038/.github/workflows/publish-dev.yml +0 -105
  17. uipath-2.0.19.dev1002910038/src/uipath/_cli/_utils/_common.py +0 -24
  18. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.cursorrules +0 -0
  19. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.editorconfig +0 -0
  20. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.gitattributes +0 -0
  21. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.github/workflows/build.yml +0 -0
  22. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.github/workflows/cd.yml +0 -0
  23. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.github/workflows/ci.yml +0 -0
  24. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.github/workflows/commitlint.yml +0 -0
  25. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.github/workflows/lint.yml +0 -0
  26. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.github/workflows/test.yml +0 -0
  27. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.gitignore +0 -0
  28. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.pre-commit-config.yaml +0 -0
  29. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.python-version +0 -0
  30. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.vscode/extensions.json +0 -0
  31. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/.vscode/settings.json +0 -0
  32. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/CONTRIBUTING.md +0 -0
  33. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/LICENSE +0 -0
  34. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/README.md +0 -0
  35. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/CONTRIBUTING.md +0 -0
  36. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/actions.md +0 -0
  37. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/assets/uipath-logo.svg +0 -0
  38. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/assets.md +0 -0
  39. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/buckets.md +0 -0
  40. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/connections.md +0 -0
  41. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/context_grounding.md +0 -0
  42. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/getting_started_agent.md +0 -0
  43. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/getting_started_cli.md +0 -0
  44. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/getting_started_sdk.md +0 -0
  45. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/index.md +0 -0
  46. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/jobs.md +0 -0
  47. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/processes.md +0 -0
  48. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/queues.md +0 -0
  49. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/docs/sdk.md +0 -0
  50. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/justfile +0 -0
  51. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/mkdocs.yml +0 -0
  52. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/py.typed +0 -0
  53. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/__init__.py +0 -0
  54. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/README.md +0 -0
  55. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/_models.py +0 -0
  56. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/_oidc_utils.py +0 -0
  57. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/_portal_service.py +0 -0
  58. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/_utils.py +0 -0
  59. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/auth_config.json +0 -0
  60. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/index.html +0 -0
  61. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/localhost.crt +0 -0
  62. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_auth/localhost.key +0 -0
  63. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_runtime/_contracts.py +0 -0
  64. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_runtime/_logging.py +0 -0
  65. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_runtime/_runtime.py +0 -0
  66. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_templates/.psmdcp.template +0 -0
  67. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_templates/.rels.template +0 -0
  68. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_templates/[Content_Types].xml.template +0 -0
  69. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_templates/main.py.template +0 -0
  70. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_templates/package.nuspec.template +0 -0
  71. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_utils/_input_args.py +0 -0
  72. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/_utils/_parse_ast.py +0 -0
  73. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/cli_deploy.py +0 -0
  74. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/cli_run.py +0 -0
  75. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_cli/middlewares.py +0 -0
  76. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_config.py +0 -0
  77. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_execution_context.py +0 -0
  78. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_folder_context.py +0 -0
  79. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/__init__.py +0 -0
  80. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/_base_service.py +0 -0
  81. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/actions_service.py +0 -0
  82. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/api_client.py +0 -0
  83. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/assets_service.py +0 -0
  84. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/buckets_service.py +0 -0
  85. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/connections_service.py +0 -0
  86. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/connections_service.pyi +0 -0
  87. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/context_grounding_service.py +0 -0
  88. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/folder_service.py +0 -0
  89. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/jobs_service.py +0 -0
  90. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/llm_gateway_service.py +0 -0
  91. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/processes_service.py +0 -0
  92. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_services/queues_service.py +0 -0
  93. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_uipath.py +0 -0
  94. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/__init__.py +0 -0
  95. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/_endpoint.py +0 -0
  96. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/_infer_bindings.py +0 -0
  97. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/_logs.py +0 -0
  98. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/_request_override.py +0 -0
  99. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/_request_spec.py +0 -0
  100. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/_user_agent.py +0 -0
  101. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/_utils/constants.py +0 -0
  102. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/__init__.py +0 -0
  103. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/action_schema.py +0 -0
  104. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/actions.py +0 -0
  105. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/assets.py +0 -0
  106. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/connections.py +0 -0
  107. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/context_grounding.py +0 -0
  108. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/context_grounding_index.py +0 -0
  109. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/exceptions.py +0 -0
  110. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/interrupt_models.py +0 -0
  111. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/job.py +0 -0
  112. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/llm_gateway.py +0 -0
  113. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/processes.py +0 -0
  114. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/models/queues.py +0 -0
  115. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/py.typed +0 -0
  116. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/tracing/__init__.py +0 -0
  117. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/tracing/_otel_exporters.py +0 -0
  118. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/tracing/_traced.py +0 -0
  119. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/src/uipath/tracing/_utils.py +0 -0
  120. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/__init__.py +0 -0
  121. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/cli/test_init.py +0 -0
  122. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/conftest.py +0 -0
  123. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/sdk/services/test_llm_integration.py +0 -0
  124. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/sdk/services/test_llm_service.py +0 -0
  125. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/sdk/services/test_uipath_llm_integration.py +0 -0
  126. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/sdk/test_config.py +0 -0
  127. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/tracing/test_otel_exporters.py +0 -0
  128. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/tracing/test_span_utils.py +0 -0
  129. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/tracing/test_traced.py +0 -0
  130. {uipath-2.0.19.dev1002910038 → uipath-2.0.21}/tests/tracing/test_tracing_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath
3
- Version: 2.0.19.dev1002910038
3
+ Version: 2.0.21
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
@@ -21,9 +21,9 @@ Requires-Dist: pydantic>=2.11.1
21
21
  Requires-Dist: pytest-asyncio>=0.25.3
22
22
  Requires-Dist: python-dotenv>=1.0.1
23
23
  Requires-Dist: requests>=2.32.3
24
+ Requires-Dist: rich>=13.0.0
24
25
  Requires-Dist: tenacity>=9.0.0
25
26
  Requires-Dist: tomli>=2.2.1
26
- Requires-Dist: twine>=6.1.0
27
27
  Requires-Dist: types-requests>=2.32.0.20250306
28
28
  Provides-Extra: langchain
29
29
  Requires-Dist: uipath-langchain<0.1.0,>=0.0.88; extra == 'langchain'
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "uipath"
3
- version = "2.0.19.dev1002910038"
3
+ version = "2.0.21"
4
4
  description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
5
5
  readme = { file = "README.md", content-type = "text/markdown" }
6
6
  requires-python = ">=3.10"
@@ -16,7 +16,7 @@ dependencies = [
16
16
  "tomli>=2.2.1",
17
17
  "types-requests>=2.32.0.20250306",
18
18
  "pathlib>=1.0.1",
19
- "twine>=6.1.0",
19
+ "rich>=13.0.0",
20
20
  ]
21
21
  classifiers = [
22
22
  "Development Status :: 3 - Alpha",
@@ -6,6 +6,7 @@ import click
6
6
  from .cli_auth import auth as auth # type: ignore
7
7
  from .cli_deploy import deploy as deploy # type: ignore
8
8
  from .cli_init import init as init # type: ignore
9
+ from .cli_invoke import invoke as invoke # type: ignore
9
10
  from .cli_new import new as new # type: ignore
10
11
  from .cli_pack import pack as pack # type: ignore
11
12
  from .cli_publish import publish as publish # type: ignore
@@ -52,3 +53,4 @@ cli.add_command(publish)
52
53
  cli.add_command(run)
53
54
  cli.add_command(deploy)
54
55
  cli.add_command(auth)
56
+ cli.add_command(invoke)
@@ -5,6 +5,7 @@ import socketserver
5
5
  import ssl
6
6
  import time
7
7
 
8
+ import click
8
9
  from dotenv import load_dotenv
9
10
 
10
11
  from ._oidc_utils import get_auth_config
@@ -38,7 +39,7 @@ def make_request_handler_class(state, code_verifier, token_callback, domain):
38
39
  content_length = int(self.headers["Content-Length"])
39
40
  post_data = self.rfile.read(content_length)
40
41
  token_data = json.loads(post_data.decode("utf-8"))
41
- print("Received authentication information")
42
+ click.echo("Received authentication information")
42
43
 
43
44
  self.send_response(200)
44
45
  self.end_headers()
@@ -179,7 +180,7 @@ class HTTPSServer:
179
180
  while not self.should_shutdown:
180
181
  self.httpd.handle_request()
181
182
  except KeyboardInterrupt:
182
- print("Process interrupted by user")
183
+ click.echo("Process interrupted by user")
183
184
  finally:
184
185
  self.stop()
185
186
 
@@ -0,0 +1,45 @@
1
+ import os
2
+ from typing import Optional
3
+
4
+ import click
5
+
6
+ from ..spinner import Spinner
7
+
8
+
9
+ def environment_options(function):
10
+ function = click.option(
11
+ "--alpha",
12
+ "domain",
13
+ flag_value="alpha",
14
+ help="Use alpha environment",
15
+ )(function)
16
+ function = click.option(
17
+ "--staging",
18
+ "domain",
19
+ flag_value="staging",
20
+ help="Use staging environment",
21
+ )(function)
22
+ function = click.option(
23
+ "--cloud",
24
+ "domain",
25
+ flag_value="cloud",
26
+ default=True,
27
+ help="Use production environment",
28
+ )(function)
29
+ return function
30
+
31
+
32
+ def get_env_vars(spinner: Optional[Spinner] = None) -> list[str | None]:
33
+ base_url = os.environ.get("UIPATH_URL")
34
+ token = os.environ.get("UIPATH_ACCESS_TOKEN")
35
+
36
+ if not all([base_url, token]):
37
+ if spinner:
38
+ spinner.stop()
39
+ click.echo(
40
+ "❌ Missing required environment variables. Please check your .env file contains:"
41
+ )
42
+ click.echo("UIPATH_URL, UIPATH_ACCESS_TOKEN")
43
+ click.get_current_context().exit(1)
44
+
45
+ return [base_url, token]
@@ -0,0 +1,29 @@
1
+ from typing import Optional, Tuple
2
+
3
+ import click
4
+ import requests
5
+
6
+ from ..spinner import Spinner
7
+
8
+
9
+ def get_personal_workspace_info(
10
+ base_url: str, token: str, spinner: Optional[Spinner] = None
11
+ ) -> Tuple[str, str]:
12
+ user_url = f"{base_url}/orchestrator_/odata/Users/UiPath.Server.Configuration.OData.GetCurrentUserExtended?$expand=PersonalWorkspace"
13
+ user_response = requests.get(user_url, headers={"Authorization": f"Bearer {token}"})
14
+
15
+ if user_response.status_code != 200:
16
+ if spinner:
17
+ spinner.stop()
18
+ click.echo("❌ Failed to get user info. Please try reauthenticating.")
19
+ click.get_current_context().exit(1)
20
+
21
+ user_data = user_response.json()
22
+ feed_id = user_data.get("PersonalWorskpaceFeedId")
23
+ folder_id = user_data["PersonalWorkspace"].get("Id")
24
+ if not (feed_id and folder_id):
25
+ if spinner:
26
+ spinner.stop()
27
+ click.echo("❌ No personal workspace found for user")
28
+ click.get_current_context().exit(1)
29
+ return feed_id, folder_id
@@ -0,0 +1,49 @@
1
+ import json
2
+ import urllib.parse
3
+ from typing import Any, Optional
4
+
5
+ import click
6
+ import requests
7
+
8
+ from ..spinner import Spinner
9
+
10
+
11
+ def get_release_info(
12
+ base_url: str,
13
+ token: str,
14
+ package_name: str,
15
+ folder_id: str,
16
+ spinner: Optional[Spinner] = None,
17
+ ) -> None | tuple[Any, Any] | tuple[None, None]:
18
+ headers = {
19
+ "Authorization": f"Bearer {token}",
20
+ "x-uipath-organizationunitid": str(folder_id),
21
+ }
22
+
23
+ release_url = f"{base_url}/orchestrator_/odata/Releases/UiPath.Server.Configuration.OData.ListReleases?$select=Id,Key&$top=1&$filter=(contains(Name,%27{urllib.parse.quote(package_name)}%27))&$orderby=Name%20asc"
24
+ response = requests.get(release_url, headers=headers)
25
+ if response.status_code == 200:
26
+ try:
27
+ data = json.loads(response.text)
28
+ release_id = data["value"][0]["Id"]
29
+ release_key = data["value"][0]["Key"]
30
+ return release_id, release_key
31
+ except KeyError:
32
+ if spinner:
33
+ spinner.stop()
34
+ click.echo("\n⚠️ Warning: Failed to deserialize release data")
35
+ return None, None
36
+ except IndexError:
37
+ if spinner:
38
+ spinner.stop()
39
+ click.echo(
40
+ "\n❌ Process not found in your workspace. Try publishing it first."
41
+ )
42
+ click.get_current_context().exit(1)
43
+
44
+ else:
45
+ if spinner:
46
+ spinner.stop()
47
+ click.echo("\n⚠️ Warning: Failed to fetch release info")
48
+ click.echo(f"Status code: {response.status_code}")
49
+ return None, None
@@ -12,6 +12,7 @@ from ._auth._oidc_utils import get_auth_config, get_auth_url
12
12
  from ._auth._portal_service import PortalService, select_tenant
13
13
  from ._auth._utils import update_auth_file, update_env_file
14
14
  from ._utils._common import environment_options
15
+ from .spinner import Spinner
15
16
 
16
17
  load_dotenv()
17
18
 
@@ -37,7 +38,7 @@ def set_port():
37
38
  if is_port_in_use(port_option_two):
38
39
  if is_port_in_use(port_option_three):
39
40
  raise RuntimeError(
40
- "All configured ports are in use. Please close applications using ports or configure different ports."
41
+ "All configured ports are in use. Please close applications using ports or configure different ports."
41
42
  )
42
43
  else:
43
44
  port = port_option_three
@@ -56,6 +57,8 @@ def set_port():
56
57
  @environment_options
57
58
  def auth(domain="alpha"):
58
59
  """Authenticate with UiPath Cloud Platform."""
60
+ spinner = Spinner("Authenticating with UiPath...")
61
+ spinner.start()
59
62
  portal_service = PortalService(domain)
60
63
  if (
61
64
  os.getenv("UIPATH_URL")
@@ -64,9 +67,13 @@ def auth(domain="alpha"):
64
67
  ):
65
68
  try:
66
69
  portal_service.ensure_valid_token()
67
- click.echo("Authentication successful")
70
+ spinner.stop()
71
+ click.echo(
72
+ click.style("✓ ", fg="green", bold=True) + "Authentication successful"
73
+ )
68
74
  return
69
75
  except Exception:
76
+ spinner.stop()
70
77
  click.echo(
71
78
  "Authentication not found or expired. Please authenticate again."
72
79
  )
@@ -75,23 +82,26 @@ def auth(domain="alpha"):
75
82
 
76
83
  webbrowser.open(auth_url, 1)
77
84
  auth_config = get_auth_config()
78
-
85
+ spinner.stop()
79
86
  print(
80
87
  "If a browser window did not open, please open the following URL in your browser:"
81
88
  )
82
89
  print(auth_url)
90
+
83
91
  server = HTTPSServer(port=auth_config["port"])
84
92
  token_data = server.start(state, code_verifier, domain)
85
- try:
86
- if token_data:
87
- portal_service.update_token_data(token_data)
88
- update_auth_file(token_data)
89
- access_token = token_data["access_token"]
90
- update_env_file({"UIPATH_ACCESS_TOKEN": access_token})
91
93
 
92
- tenants_and_organizations = portal_service.get_tenants_and_organizations()
93
- select_tenant(domain, tenants_and_organizations)
94
- else:
95
- click.echo("Authentication failed")
96
- except Exception as e:
97
- click.echo(f"Authentication failed: {e}")
94
+ if token_data:
95
+ portal_service.update_token_data(token_data)
96
+ update_auth_file(token_data)
97
+ access_token = token_data["access_token"]
98
+ update_env_file({"UIPATH_ACCESS_TOKEN": access_token})
99
+
100
+ tenants_and_organizations = portal_service.get_tenants_and_organizations()
101
+ select_tenant(domain, tenants_and_organizations)
102
+ click.echo(
103
+ click.style("✓ ", fg="green", bold=True)
104
+ + "Authentication completed successfully!"
105
+ )
106
+ else:
107
+ click.echo("❌ Authentication failed")
@@ -11,6 +11,7 @@ import click
11
11
  from ._utils._input_args import generate_args
12
12
  from ._utils._parse_ast import generate_bindings_json
13
13
  from .middlewares import Middlewares
14
+ from .spinner import Spinner
14
15
 
15
16
 
16
17
  def generate_env_file(target_directory):
@@ -51,6 +52,7 @@ def get_user_script(directory: str, entrypoint: Optional[str] = None) -> Optiona
51
52
  @click.argument("entrypoint", required=False, default=None)
52
53
  def init(entrypoint: str) -> None:
53
54
  """Initialize a uipath.json configuration file for the script."""
55
+ spinner = Spinner("Initializing UiPath project...")
54
56
  current_directory = os.getcwd()
55
57
  generate_env_file(current_directory)
56
58
 
@@ -67,12 +69,11 @@ def init(entrypoint: str) -> None:
67
69
 
68
70
  if not result.should_continue:
69
71
  return
70
-
71
72
  script_path = get_user_script(current_directory, entrypoint=entrypoint)
72
73
 
73
74
  if not script_path:
74
75
  click.get_current_context().exit(1)
75
-
76
+ spinner.start()
76
77
  try:
77
78
  args = generate_args(script_path)
78
79
 
@@ -94,21 +95,23 @@ def init(entrypoint: str) -> None:
94
95
  # Generate bindings JSON based on the script path
95
96
  try:
96
97
  bindings_data = generate_bindings_json(script_path)
97
-
98
98
  # Add bindings to the config data
99
99
  config_data["bindings"] = bindings_data
100
-
101
- click.echo("Bindings generated successfully.")
102
100
  except Exception as e:
103
- click.echo(f"Warning: Could not generate bindings: {str(e)}")
101
+ click.echo(f"⚠️ Warning: Could not generate bindings: {str(e)}")
104
102
 
105
103
  config_path = "uipath.json"
106
104
  with open(config_path, "w") as config_file:
107
105
  json.dump(config_data, config_file, indent=4)
108
106
 
109
- click.echo(f"Configuration file {config_path} created successfully.")
107
+ spinner.stop()
108
+ click.echo(
109
+ click.style("✓ ", fg="green", bold=True)
110
+ + f"Configuration file {config_path} created successfully."
111
+ )
110
112
 
111
113
  except Exception as e:
112
- click.echo(f"Error generating configuration: {str(e)}")
114
+ spinner.stop()
115
+ click.echo(f"❌ Error generating configuration: {str(e)}")
113
116
  click.echo(traceback.format_exc())
114
117
  click.get_current_context().exit(1)
@@ -0,0 +1,105 @@
1
+ # type: ignore
2
+ import logging
3
+ import os
4
+ from typing import Optional
5
+
6
+ import click
7
+ import requests
8
+ from dotenv import load_dotenv
9
+
10
+ from .spinner import Spinner
11
+
12
+ try:
13
+ import tomllib
14
+ except ImportError:
15
+ import tomli as tomllib
16
+
17
+ from ._utils._common import get_env_vars
18
+ from ._utils._folders import get_personal_workspace_info
19
+ from ._utils._processes import get_release_info
20
+
21
+ logger = logging.getLogger(__name__)
22
+ load_dotenv()
23
+
24
+
25
+ def _read_project_name() -> str:
26
+ current_path = os.getcwd()
27
+ toml_path = os.path.join(current_path, "pyproject.toml")
28
+ if not os.path.isfile(toml_path):
29
+ raise Exception("pyproject.toml not found")
30
+
31
+ with open(toml_path, "rb") as f:
32
+ content = tomllib.load(f)
33
+ if "project" not in content:
34
+ raise Exception("pyproject.toml is missing the required field: project")
35
+ if "name" not in content["project"]:
36
+ raise Exception(
37
+ "pyproject.toml is missing the required field: project.name"
38
+ )
39
+
40
+ return content["project"]["name"]
41
+
42
+
43
+ @click.command()
44
+ @click.argument("entrypoint", required=False)
45
+ @click.argument("input", required=False, default="{}")
46
+ def invoke(entrypoint: Optional[str], input: Optional[str]) -> None:
47
+ """Invoke a remote agent with JSON input."""
48
+ spinner = Spinner("Starting job...")
49
+ spinner.start()
50
+
51
+ current_path = os.getcwd()
52
+ load_dotenv(os.path.join(current_path, ".env"), override=True)
53
+ [base_url, token] = get_env_vars(spinner)
54
+
55
+ url = f"{base_url}/orchestrator_/odata/Jobs/UiPath.Server.Configuration.OData.StartJobs"
56
+ _, personal_workspace_folder_id = get_personal_workspace_info(
57
+ base_url, token, spinner
58
+ )
59
+ project_name = _read_project_name()
60
+
61
+ _, release_key = get_release_info(
62
+ base_url, token, project_name, personal_workspace_folder_id, spinner
63
+ )
64
+ payload = {
65
+ "StartInfo": {
66
+ "ReleaseKey": str(release_key),
67
+ "RunAsMe": True,
68
+ "InputArguments": input,
69
+ "EntryPointPath": entrypoint,
70
+ }
71
+ }
72
+ headers = {
73
+ "Authorization": f"Bearer {token}",
74
+ "x-uipath-organizationunitid": str(personal_workspace_folder_id),
75
+ }
76
+
77
+ response = requests.post(url, json=payload, headers=headers)
78
+ spinner.stop()
79
+
80
+ if response.status_code == 201:
81
+ job_key = None
82
+ try:
83
+ job_key = response.json()["value"][0]["Key"]
84
+ except KeyError:
85
+ click.echo("Error: Failed to get job key from response")
86
+ click.Abort()
87
+ if job_key:
88
+ job_url = f"{base_url}/orchestrator_/jobs(sidepanel:sidepanel/jobs/{job_key}/details)?fid={personal_workspace_folder_id}"
89
+ click.echo("\n✨ Job started successfully!")
90
+ click.echo(
91
+ "\n🔗 Monitor your job here: "
92
+ + click.style(
93
+ f"\u001b]8;;{job_url}\u001b\\{job_url}\u001b]8;;\u001b\\",
94
+ fg="bright_blue",
95
+ bold=True,
96
+ )
97
+ + "\n"
98
+ )
99
+ else:
100
+ click.echo(f"\n❌ Error starting job: {response.text}")
101
+ click.Abort()
102
+
103
+
104
+ if __name__ == "__main__":
105
+ invoke()
@@ -6,6 +6,7 @@ import traceback
6
6
  import click
7
7
 
8
8
  from .middlewares import Middlewares
9
+ from .spinner import Spinner
9
10
 
10
11
 
11
12
  def generate_script(target_directory):
@@ -37,6 +38,7 @@ requires-python = ">=3.9"
37
38
  @click.command()
38
39
  @click.argument("name", type=str, default="")
39
40
  def new(name: str):
41
+ spinner = Spinner("Creating new project...")
40
42
  directory = os.getcwd()
41
43
 
42
44
  if not name:
@@ -44,12 +46,15 @@ def new(name: str):
44
46
  "Please specify a name for your project\n`uipath new hello-world`"
45
47
  )
46
48
 
47
- click.echo(f"Initializing project {name} in current directory..")
49
+ click.echo(
50
+ click.style("✓ ", fg="green", bold=True)
51
+ + f"Initializing project {name} in current directory.."
52
+ )
48
53
 
49
54
  result = Middlewares.next("new", name)
50
55
 
51
56
  if result.error_message:
52
- click.echo(result.error_message)
57
+ click.echo("❌ " + result.error_message)
53
58
  if result.should_include_stacktrace:
54
59
  click.echo(traceback.format_exc())
55
60
  click.get_current_context().exit(1)
@@ -61,13 +66,14 @@ def new(name: str):
61
66
  return
62
67
 
63
68
  generate_script(directory)
64
- click.echo("Created main.py file.")
69
+ click.echo(click.style("✓ ", fg="green", bold=True) + "Created main.py file")
65
70
  generate_pyproject(directory, name)
66
- click.echo("Created pyproject.toml file.")
67
-
71
+ click.echo(click.style("✓ ", fg="green", bold=True) + "Created pyproject.toml file")
72
+ spinner.start()
68
73
  ctx = click.get_current_context()
69
74
  init_cmd = ctx.parent.command.get_command(ctx, "init")
70
75
  ctx.invoke(init_cmd)
76
+ spinner.stop()
71
77
 
72
78
  click.echo("""` uipath run main.py '{"message": "Hello World!"}' `""")
73
79
 
@@ -12,6 +12,8 @@ try:
12
12
  except ImportError:
13
13
  import tomli as tomllib
14
14
 
15
+ from .spinner import Spinner
16
+
15
17
  schema = "https://cloud.uipath.com/draft/2024-12/entry-point"
16
18
 
17
19
 
@@ -328,7 +330,7 @@ def read_toml_project(file_path: str) -> dict[str, any]:
328
330
  def get_project_version(directory):
329
331
  toml_path = os.path.join(directory, "pyproject.toml")
330
332
  if not os.path.exists(toml_path):
331
- click.echo("Warning: No pyproject.toml found. Using default version 0.0.1")
333
+ click.echo("⚠️ Warning: No pyproject.toml found. Using default version 0.0.1")
332
334
  return "0.0.1"
333
335
  toml_data = read_toml_project(toml_path)
334
336
  return toml_data["version"]
@@ -341,38 +343,50 @@ def pack(root):
341
343
 
342
344
  while not os.path.isfile(os.path.join(root, "uipath.json")):
343
345
  click.echo(
344
- "uipath.json not found. Please run `uipath init` in the project directory."
346
+ "uipath.json not found. Please run `uipath init` in the project directory."
345
347
  )
346
348
  return
347
349
  config = check_config(root)
348
350
  if not config["project_name"] or config["project_name"].strip() == "":
349
- raise Exception("Project name cannot be empty")
351
+ raise Exception("Project name cannot be empty")
350
352
 
351
353
  if not config["description"] or config["description"].strip() == "":
352
- raise Exception("Project description cannot be empty")
354
+ raise Exception("Project description cannot be empty")
353
355
 
354
356
  if not config["authors"] or config["authors"].strip() == "":
355
- raise Exception("Project authors cannot be empty")
357
+ raise Exception("Project authors cannot be empty")
356
358
 
357
359
  invalid_chars = ["&", "<", ">", '"', "'", ";"]
358
360
  for char in invalid_chars:
359
361
  if char in config["project_name"]:
360
- raise Exception(f"Project name contains invalid character: '{char}'")
362
+ raise Exception(f"Project name contains invalid character: '{char}'")
361
363
 
362
364
  for char in invalid_chars:
363
365
  if char in config["description"]:
364
- raise Exception(f"Project description contains invalid character: '{char}'")
365
- click.echo(
366
+ raise Exception(
367
+ f"❌ Project description contains invalid character: '{char}'"
368
+ )
369
+ spinner = Spinner(
366
370
  f"Packaging project {config['project_name']}:{version or config['version']} description {config['description']} authored by {config['authors']}"
367
371
  )
368
- pack_fn(
369
- config["project_name"],
370
- config["description"],
371
- config["entryPoints"],
372
- version or config["version"],
373
- config["authors"],
374
- root,
375
- )
372
+ try:
373
+ spinner.start()
374
+ pack_fn(
375
+ config["project_name"],
376
+ config["description"],
377
+ config["entryPoints"],
378
+ version or config["version"],
379
+ config["authors"],
380
+ root,
381
+ )
382
+ spinner.stop()
383
+ click.echo(
384
+ click.style("✓ ", fg="green", bold=True) + "Package created successfully!"
385
+ )
386
+ except Exception as e:
387
+ spinner.stop()
388
+ click.echo(f"\n❌ Error: {str(e)}")
389
+ click.Abort()
376
390
 
377
391
 
378
392
  if __name__ == "__main__":