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
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2026 Huawei Technologies Co., Ltd. All rights reserved.
Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -199,4 +199,4 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "uv_build"

[project]
name = "agentarts-sdk"
version = "0.1.1"
version = "0.1.2"
description = "Huawei Cloud AgentArts SDK - Build, deploy and manage AI agents with cloud capabilities"
readme = "README.md"
license = {file = "LICENSE"}
Expand Down
4 changes: 2 additions & 2 deletions src/agentarts/sdk/service/runtime_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ def invoke_agent(
"""
from agentarts.sdk.runtime.model import SESSION_HEADER, USER_ID_HEADER

path = f"/agent/{agent_name}/invocations"
path = f"/runtimes/{agent_name}/invocations"
params: dict[str, Any] = {}
if endpoint:
params["endpoint"] = endpoint
Expand Down Expand Up @@ -721,7 +721,7 @@ def ping_agent(

result = self._data(
"GET",
f"/agent/{agent_name}/ping",
f"/runtimes/{agent_name}/ping",
params=params if params else None,
headers=headers if headers else None,
timeout=timeout,
Expand Down
4 changes: 2 additions & 2 deletions src/agentarts/sdk/service/swr_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def get_organization(self, organization: str) -> dict[str, Any] | None:
}

except Exception as e:
print(f"Organization '{organization}' not found: {e}")
print(f"Organization '{organization}' query failed: {e}")
return None

def create_organization(
Expand Down Expand Up @@ -253,7 +253,7 @@ def get_repository(
}

except Exception as e:
print(f"Repository '{organization}/{repository}' not found: {e}")
print(f"Repository '{organization}/{repository}' query failed: {e}")
return None

def create_repository(
Expand Down
3 changes: 2 additions & 1 deletion src/agentarts/toolkit/cli/runtime/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
echo_info,
echo_success,
)
from agentarts.toolkit.utils.swr_org import generate_swr_org_name

console = Console()

Expand Down Expand Up @@ -111,7 +112,7 @@ def main(
if org is None:
existing_config = config_op.get_agent(agent_name)
default_org = existing_config.swr_config.organization if existing_config else None
auto_org = "agentarts-org"
auto_org = generate_swr_org_name(region=agent_region)

console.print("\n[bold]SWR Organization:[/bold]")
if default_org:
Expand Down
6 changes: 4 additions & 2 deletions src/agentarts/toolkit/cli/runtime/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from rich.prompt import Prompt

from agentarts.toolkit.operations.runtime import init as init_op
from agentarts.toolkit.utils.swr_org import generate_default_agent_name

console = Console()

Expand Down Expand Up @@ -53,7 +54,8 @@ def prompt_for_template() -> TemplateType:

def prompt_for_name() -> str:
"""Prompt user to enter project name"""
return Prompt.ask("\n[bold]Enter project name[/bold]", default="myagent")
default_name = generate_default_agent_name()
return Prompt.ask("\n[bold]Enter project name[/bold]", default=default_name)


def prompt_for_region() -> str:
Expand Down Expand Up @@ -83,7 +85,7 @@ def init(
] = None,
swr_org: Annotated[
str | None,
typer.Option("--swr-org", help="SWR organization (default: agentarts-org)"),
typer.Option("--swr-org", help="SWR organization (auto-generated if not specified)"),
] = None,
swr_repo: Annotated[
str | None,
Expand Down
6 changes: 4 additions & 2 deletions src/agentarts/toolkit/operations/runtime/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
BaseConfig,
SWRConfig,
)
from agentarts.toolkit.utils.swr_org import generate_swr_org_name

console = Console()

Expand Down Expand Up @@ -227,7 +228,8 @@ def add_agent(
existing_dict.setdefault("swr_config", {})["repository_auto_create"] = repository_auto_create

final_region = existing_dict.get("base", {}).get("region", "cn-southwest-2")
final_org = existing_dict.get("swr_config", {}).get("organization", "agentarts-org")
existing_org = existing_dict.get("swr_config", {}).get("organization")
final_org = existing_org or generate_swr_org_name(region=final_region)
final_repo = existing_dict.get("swr_config", {}).get("repository", f"agent_{name}")

artifact_url = f"swr.{final_region}.myhuaweicloud.com/{final_org}/{final_repo}:latest"
Expand All @@ -253,7 +255,7 @@ def add_agent(
)

final_region = region or "cn-southwest-2"
final_org = swr_organization or "agentarts-org"
final_org = swr_organization or generate_swr_org_name(region=final_region)
final_repo = swr_repository or f"agent_{name}"

artifact_url = f"swr.{final_region}.myhuaweicloud.com/{final_org}/{final_repo}:latest"
Expand Down
3 changes: 2 additions & 1 deletion src/agentarts/toolkit/operations/runtime/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
echo_step,
echo_success,
)
from agentarts.toolkit.utils.swr_org import generate_swr_org_name
from agentarts.toolkit.utils.templates.manager import template_manager

console = Console()
Expand Down Expand Up @@ -148,7 +149,7 @@ def create_config_file(
) -> None:
"""Create .agentarts_config.yaml configuration file."""
actual_region = region or "cn-southwest-2"
actual_swr_org = swr_org or "agentarts-org"
actual_swr_org = swr_org or generate_swr_org_name(region=actual_region)
actual_swr_repo = swr_repo or f"agent_{name}"
detected_platform = detect_platform()

Expand Down
141 changes: 141 additions & 0 deletions src/agentarts/toolkit/utils/swr_org.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""SWR organization name generator."""

import hashlib
import random
import string

from agentarts.sdk.utils.constant import get_ak


def shorten_region(region: str) -> str:
"""
Shorten region name to a compact form.

Examples:
cn-southwest-2 -> cnsw2
cn-north-4 -> cnno4
ap-southeast-1 -> apse1

Args:
region: Full region name (e.g., 'cn-southwest-2')

Returns:
Shortened region name (max 6 chars)
"""
parts = region.split("-")
if len(parts) >= 3:
provider = parts[0][:2]
area = parts[1][:2]
num = parts[2] if len(parts) > 2 else ""
if len(num) > 2:
num = num[:2]
return f"{provider}{area}{num}"
return region.replace("-", "")[:6]


def generate_ak_identifier(ak: str | None = None, length: int = 8) -> str:
"""
Generate identifier from AK (Access Key).

If AK is available, uses hash of AK to generate consistent identifier.
If AK is not available, generates random identifier.

Args:
ak: Access Key string. If None, will try to get from environment.
length: Length of identifier to generate (default 8)

Returns:
Identifier string of specified length
"""
if ak is None:
ak = get_ak()

if ak and len(ak) > 0:
hash_obj = hashlib.md5(ak.encode(), usedforsecurity=False)
hash_hex = hash_obj.hexdigest()
return hash_hex[:length].lower()

chars = string.ascii_lowercase + string.digits
return "".join(random.choices(chars, k=length))


def generate_random_suffix(length: int = 6) -> str:
"""
Generate random suffix for uniqueness.

Args:
length: Length of random suffix (default 6)

Returns:
Random string of lowercase letters and digits
"""
chars = string.ascii_lowercase + string.digits
return "".join(random.choices(chars, k=length))


def generate_default_agent_name(base_name: str = "myagent", suffix_length: int = 5) -> str:
"""
Generate default agent name with random suffix.

Args:
base_name: Base name for the agent (default: 'myagent')
suffix_length: Length of random suffix (default 5)

Returns:
Agent name with random suffix (e.g., 'myagent-abc12')
"""
suffix = generate_random_suffix(suffix_length)
return f"{base_name}-{suffix}"


def generate_swr_org_name(
region: str | None = None,
ak: str | None = None,
max_length: int = 64,
) -> str:
"""
Generate unique SWR organization name.

Format: agentarts-{region_short}-{ak_identifier}-org

The generated name is designed to be:
1. Unique per account (based on AK hash)
2. Consistent per account (same AK generates same name)
3. Within max_length constraint (default 64 chars)

Args:
region: Huawei Cloud region (e.g., 'cn-southwest-2')
If None, uses 'default' as placeholder
ak: Access Key for account identification
If None, will try to get from environment
max_length: Maximum length of organization name (default 64)

Returns:
Unique SWR organization name

Examples:
>>> generate_swr_org_name("cn-southwest-2", "ABCDEFGHIJKLMNOP")
'agentarts-cnso2-19fc8eff-org'

>>> generate_swr_org_name("cn-southwest-2") # AK from env
'agentarts-cnso2-<ak_hash>-org'
"""
prefix = "agentarts-"
suffix = "-org"

region_short = shorten_region(region or "default")

ak_identifier = generate_ak_identifier(ak, length=8)

base_name = f"{prefix}{region_short}-{ak_identifier}{suffix}"

if len(base_name) > max_length:
excess = len(base_name) - max_length
ak_identifier = generate_ak_identifier(ak, length=8 - min(excess, 8))
base_name = f"{prefix}{region_short}-{ak_identifier}{suffix}"

if len(base_name) > max_length:
region_short = region_short[: len(region_short) - min(len(base_name) - max_length, len(region_short))]
base_name = f"{prefix}{region_short}{suffix}"

return base_name.lower()
Loading