Skip to content

Commit a8fe199

Browse files
authored
Merge pull request #688 from UiPath/feat/create-project-in-solution
2 parents c75802f + 36fa816 commit a8fe199

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath"
3-
version = "2.1.83"
3+
version = "2.1.84"
44
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.10"

src/uipath/_cli/_push/sw_file_handler.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import click
99

10+
from ...models.exceptions import EnrichedException
1011
from .._utils._console import ConsoleLogger
1112
from .._utils._constants import (
1213
AGENT_INITIAL_CODE_VERSION,
@@ -483,7 +484,15 @@ async def upload_source_files(self, config_data: dict[str, Any]) -> None:
483484
Raises:
484485
Exception: If any step in the process fails
485486
"""
486-
structure = await self._studio_client.get_project_structure_async()
487+
try:
488+
structure = await self._studio_client.get_project_structure_async()
489+
except EnrichedException as e:
490+
if e.status_code == 404:
491+
structure = ProjectStructure(name="", files=[], folders=[])
492+
await self._studio_client._put_lock()
493+
else:
494+
raise
495+
487496
source_code_folder = self._get_folder_by_name(structure, "source_code")
488497
root_files, source_code_files = self._get_remote_files(
489498
structure, source_code_folder

src/uipath/_cli/_utils/_studio_project.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,45 @@ async def wrapper(self, *args, **kwargs):
224224
return wrapper
225225

226226

227+
class StudioSolutionsClient:
228+
def __init__(self, solution_id: str):
229+
from uipath import UiPath
230+
231+
self.uipath: UiPath = UiPath()
232+
self._solutions_base_url: str = f"/studio_/backend/api/Solution/{solution_id}"
233+
234+
async def create_project_async(
235+
self,
236+
project_name: str,
237+
project_type: str = "Agent",
238+
trigger_type: str = "Manual",
239+
):
240+
"""Create a new project in the specified solution.
241+
242+
Args:
243+
project_name: The name for the new project
244+
project_type: The type of project to create (default: "Agent")
245+
trigger_type: The trigger type for the project (default: "Manual")
246+
247+
Returns:
248+
dict: The created project details including project ID
249+
"""
250+
data = {
251+
"createDefaultProjectCommand[projectType]": project_type,
252+
"createDefaultProjectCommand[triggerType]": trigger_type,
253+
"createDefaultProjectCommand[name]": project_name,
254+
}
255+
256+
response = await self.uipath.api_client.request_async(
257+
"POST",
258+
url=f"{self._solutions_base_url}/projects",
259+
data=data,
260+
scoped="org",
261+
)
262+
263+
return response.json()
264+
265+
227266
class StudioClient:
228267
def __init__(self, project_id: str):
229268
from uipath import UiPath
@@ -464,3 +503,10 @@ async def _retrieve_lock(self) -> LockInfo:
464503
scoped="org",
465504
)
466505
return LockInfo.model_validate(response.json())
506+
507+
async def _put_lock(self):
508+
await self.uipath.api_client.request_async(
509+
"PUT",
510+
url=f"{self._lock_operations_base_url}/dummy-uuid-Shared?api-version=2",
511+
scoped="org",
512+
)

src/uipath/agent/_utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from pydantic import TypeAdapter
66

77
from uipath._cli._evals._models._evaluation_set import LLMMockingStrategy
8+
from uipath._cli._push.sw_file_handler import SwFileHandler
89
from uipath._cli._utils._studio_project import (
910
ProjectFile,
1011
ProjectFolder,
1112
StudioClient,
13+
StudioSolutionsClient,
1214
resolve_path,
1315
)
1416
from uipath.agent.models.agent import (
@@ -27,6 +29,20 @@ async def get_file(
2729
return await studio_client.download_file_async(resolved.id)
2830

2931

32+
async def create_agent_project(solution_id: str, project_name: str) -> str:
33+
studio_client = StudioSolutionsClient(solution_id=solution_id)
34+
project = await studio_client.create_project_async(project_name=project_name)
35+
return project["id"]
36+
37+
38+
async def upload_project_files(project_id: str, root: str) -> None:
39+
sw_file_handler = SwFileHandler(
40+
project_id=project_id,
41+
directory=root,
42+
)
43+
await sw_file_handler.upload_source_files({})
44+
45+
3046
async def load_agent_definition(project_id: str) -> AgentDefinition:
3147
studio_client = StudioClient(project_id=project_id)
3248
project_structure = await studio_client.get_project_structure_async()

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)