Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/core/tests/cli/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def test_init_with_entrypoint(runner: CliRunner, temp_dir: str) -> None:
config = json.load(f)
assert "entryPoints" in config
assert len(config["entryPoints"]) == 1
assert config["entryPoints"][0]["filePath"] == "script.py"
assert config["entryPoints"][0]["filePath"] == "content/script.py"
assert config["entryPoints"][0]["type"] == "agent"
assert "uniqueId" in config["entryPoints"][0]

Expand Down
2 changes: 2 additions & 0 deletions sdk/core/uipath_sdk/_cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import click

from .cli_deploy import deploy as deploy # type: ignore
from .cli_init import init as init # type: ignore
from .cli_new import new as new # type: ignore
from .cli_pack import pack as pack # type: ignore
Expand All @@ -17,3 +18,4 @@ def cli() -> None:
cli.add_command(pack)
cli.add_command(publish)
cli.add_command(run)
cli.add_command(deploy)
13 changes: 13 additions & 0 deletions sdk/core/uipath_sdk/_cli/cli_deploy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# type: ignore
import click

from .cli_pack import pack
from .cli_publish import publish


@click.command()
@click.argument("root", type=str, default="./")
def deploy(root):
ctx = click.get_current_context()
ctx.invoke(pack, root=root)
ctx.invoke(publish)
2 changes: 1 addition & 1 deletion sdk/core/uipath_sdk/_cli/cli_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def init(entrypoint: str) -> None:
config_data = {
"entryPoints": [
{
"filePath": relative_path,
"filePath": f"content/{relative_path}",
"uniqueId": str(uuid.uuid4()),
# "type": "process", OR BE doesn't offer json schema support for type: Process
"type": "agent",
Expand Down
22 changes: 16 additions & 6 deletions sdk/core/uipath_sdk/_cli/cli_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,25 @@ def read_toml_project(file_path: str) -> dict[str, any]:
}


def get_project_version(directory):
toml_path = os.path.join(directory, "pyproject.toml")
if not os.path.exists(toml_path):
click.echo("Warning: No pyproject.toml found. Using default version 0.0.1")
return "0.0.1"
toml_data = read_toml_project(toml_path)
return toml_data["version"]


@click.command()
@click.argument("root", type=str, default="./")
@click.argument("version", type=str, default="")
def pack(root, version):
proposed_version = get_proposed_version(root)
if proposed_version and click.confirm(f"Use version {proposed_version}?"):
version = proposed_version
def pack(root):
version = get_project_version(root)

while not os.path.isfile(os.path.join(root, "uipath.json")):
root = click.prompt("'uipath.json' not found.\nEnter your project's directory")
click.echo(
"uipath.json not found. Please run `uipath init` in the project directory."
)
return
config = check_config(root)
click.echo(
f"Packaging project {config['project_name']}:{version or config['version']} description {config['description']} authored by {config['authors']}"
Expand Down
33 changes: 10 additions & 23 deletions sdk/core/uipath_sdk/_cli/cli_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,30 +41,17 @@ def get_env_vars():


@click.command()
@click.argument("path", type=str, default="")
def publish(path):
# Search for .nupkg file
packageToPublish = None

if not path:
if not os.path.exists(".uipath"):
click.echo("No .uipath directory found in current directory")
return
def publish():
if not os.path.exists(".uipath"):
click.echo("No .uipath directory found in current directory")
return

# Find most recent .nupkg file in .uipath directory
most_recent = get_most_recent_package()
# click.echo(f"Do you want to publish {most_recent}?")
# Find most recent .nupkg file in .uipath directory
most_recent = get_most_recent_package()

if not click.confirm(f"Do you want to publish {most_recent}?"):
click.echo("Aborting publish")
return
click.echo(f"Publishing most recent package: {most_recent}")

packageToPublish = os.path.join(".uipath", most_recent)
else:
if not os.path.exists(path):
click.echo(f"{path} not found")
return
packageToPublish = path
package_to_publish_path = os.path.join(".uipath", most_recent)

# Check .env file
if not os.path.exists(".env"):
Expand All @@ -77,8 +64,8 @@ def publish(path):

headers = {"Authorization": f"Bearer {token}"}

with open(packageToPublish, "rb") as f:
files = {"file": (packageToPublish, f, "application/octet-stream")}
with open(package_to_publish_path, "rb") as f:
files = {"file": (package_to_publish_path, f, "application/octet-stream")}
response = requests.post(url, headers=headers, files=files)

if response.status_code == 200:
Expand Down
44 changes: 39 additions & 5 deletions sdk/langchain/uipath_langchain/_cli/cli_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@
from ._utils._graph import LangGraphConfig


def resolve_refs(schema, root=None):
"""Recursively resolves $ref references in a JSON schema."""
if root is None:
root = schema # Store the root schema to resolve $refs

if isinstance(schema, dict):
if "$ref" in schema:
ref_path = schema["$ref"].lstrip("#/").split("/")
ref_schema = root
for part in ref_path:
ref_schema = ref_schema.get(part, {})
return resolve_refs(ref_schema, root)

return {k: resolve_refs(v, root) for k, v in schema.items()}

elif isinstance(schema, list):
return [resolve_refs(item, root) for item in schema]

return schema


def generate_schema_from_graph(graph: Any) -> Dict[str, Any]:
"""Extract input/output schema from a LangGraph graph"""
schema = {
Expand All @@ -17,14 +38,27 @@ def generate_schema_from_graph(graph: Any) -> Dict[str, Any]:
if hasattr(graph, "input_schema"):
if hasattr(graph.input_schema, "model_json_schema"):
input_schema = graph.input_schema.model_json_schema()
schema["input"]["properties"] = input_schema.get("properties", {})
schema["input"]["required"] = input_schema.get("required", [])

unpacked_ref_def_properties = resolve_refs(input_schema)

schema["input"]["properties"] = unpacked_ref_def_properties.get(
"properties", {}
)
schema["input"]["required"] = unpacked_ref_def_properties.get(
"required", []
)

if hasattr(graph, "output_schema"):
if hasattr(graph.output_schema, "model_json_schema"):
output_schema = graph.output_schema.model_json_schema()
schema["output"]["properties"] = output_schema.get("properties", {})
schema["output"]["required"] = output_schema.get("required", [])

unpacked_ref_def_properties = resolve_refs(output_schema)
schema["output"]["properties"] = unpacked_ref_def_properties.get(
"properties", {}
)
schema["output"]["required"] = unpacked_ref_def_properties.get(
"required", []
)

return schema

Expand Down Expand Up @@ -52,7 +86,7 @@ def langgraph_init_middleware(entrypoint: str) -> MiddlewareResult:
graph_schema = generate_schema_from_graph(loaded_graph)

new_entrypoint: dict[str, Any] = {
"filePath": graph.name,
"filePath": f"content/{graph.name}",
"uniqueId": str(uuid.uuid4()),
"type": "agent",
"input": graph_schema["input"],
Expand Down