Skip to content
Open
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: 3 additions & 1 deletion agentrun/credential/__credential_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ async def create_async(
Returns:
Credential: 创建的凭证对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
async def delete_by_name_async(
Expand Down
12 changes: 9 additions & 3 deletions agentrun/credential/credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ async def create_async(
Returns:
Credential: 创建的凭证对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
def create(
Expand Down Expand Up @@ -113,7 +115,9 @@ def delete_by_name(
credential_name: 凭证名称
config: 配置
"""
return cls.__get_client(config=config).delete(credential_name, config=config)
return cls.__get_client(config=config).delete(
credential_name, config=config
)

@classmethod
async def update_by_name_async(
Expand Down Expand Up @@ -185,7 +189,9 @@ def get_by_name(cls, credential_name: str, config: Optional[Config] = None):
Returns:
Credential: 凭证对象
"""
return cls.__get_client(config=config).get(credential_name, config=config)
return cls.__get_client(config=config).get(
credential_name, config=config
)

@classmethod
async def _list_page_async(
Expand Down
4 changes: 3 additions & 1 deletion agentrun/knowledgebase/__knowledgebase_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ async def create_async(
Returns:
KnowledgeBase: 创建的知识库对象 / Created knowledge base object
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
async def delete_by_name_async(
Expand Down
8 changes: 6 additions & 2 deletions agentrun/knowledgebase/knowledgebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ async def create_async(
Returns:
KnowledgeBase: 创建的知识库对象 / Created knowledge base object
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
def create(
Expand Down Expand Up @@ -208,7 +210,9 @@ def get_by_name(
Returns:
KnowledgeBase: 知识库对象 / KnowledgeBase object
"""
return cls.__get_client(config=config).get(knowledge_base_name, config=config)
return cls.__get_client(config=config).get(
knowledge_base_name, config=config
)

@classmethod
async def _list_page_async(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ async def create_async(
Returns:
MemoryCollection: 创建的记忆集合对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
async def delete_by_name_async(
Expand Down
4 changes: 3 additions & 1 deletion agentrun/memory_collection/memory_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ async def create_async(
Returns:
MemoryCollection: 创建的记忆集合对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
def create(
Expand Down
4 changes: 3 additions & 1 deletion agentrun/model/__model_proxy_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ async def create_async(
Returns:
ModelProxy: 创建的模型服务对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
async def delete_by_name_async(
Expand Down
4 changes: 3 additions & 1 deletion agentrun/model/__model_service_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ async def create_async(
Returns:
ModelService: 创建的模型服务对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
async def delete_by_name_async(
Expand Down
4 changes: 3 additions & 1 deletion agentrun/model/model_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ async def create_async(
Returns:
ModelProxy: 创建的模型服务对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
def create(
Expand Down
4 changes: 3 additions & 1 deletion agentrun/model/model_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ async def create_async(
Returns:
ModelService: 创建的模型服务对象
"""
return await cls.__get_client(config=config).create_async(input, config=config)
return await cls.__get_client(config=config).create_async(
input, config=config
)

@classmethod
def create(
Expand Down
6 changes: 2 additions & 4 deletions agentrun/sandbox/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,8 +748,7 @@ async def delete_sandbox_async(
raise ClientError(
status_code=0,
message=(
"Failed to stop sandbox:"
f" {message or 'Unknown error'}"
f"Failed to stop sandbox: {message or 'Unknown error'}"
),
)

Expand Down Expand Up @@ -805,8 +804,7 @@ def delete_sandbox(
raise ClientError(
status_code=0,
message=(
"Failed to stop sandbox:"
f" {message or 'Unknown error'}"
f"Failed to stop sandbox: {message or 'Unknown error'}"
),
)

Expand Down
8 changes: 2 additions & 6 deletions agentrun/sandbox/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ async def create_async(
)

@classmethod
def create(
cls, input: TemplateInput, config: Optional[Config] = None
):
def create(cls, input: TemplateInput, config: Optional[Config] = None):
return cls.__get_client(config=config).create_template(
input, config=config
)
Expand Down Expand Up @@ -172,9 +170,7 @@ async def get_by_name_async(
)

@classmethod
def get_by_name(
cls, template_name: str, config: Optional[Config] = None
):
def get_by_name(cls, template_name: str, config: Optional[Config] = None):
return cls.__get_client(config=config).get_template(
template_name=template_name, config=config
)
Expand Down
24 changes: 18 additions & 6 deletions agentrun/tool/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

from enum import Enum
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Union

from agentrun.utils.model import BaseModel

Expand Down Expand Up @@ -194,8 +194,8 @@ class ToolSchema(BaseModel):
required: Optional[List[str]] = None
"""必填字段 / Required fields"""

additional_properties: Optional[bool] = None
"""是否允许额外属性 / Whether additional properties are allowed"""
additional_properties: Optional[Union[bool, "ToolSchema"]] = None
"""额外属性约束 / Additional properties constraint"""

items: Optional["ToolSchema"] = None
"""数组元素类型 / Array item type"""
Expand Down Expand Up @@ -252,7 +252,7 @@ def from_any_openapi_schema(cls, schema: Any) -> "ToolSchema":
递归解析所有嵌套结构,保留完整的 schema 信息。
Recursively parses all nested structures, preserving complete schema information.
"""
if not schema or not isinstance(schema, dict):
if schema is None or not isinstance(schema, dict):
return cls(type="string")

from pydash import get as pydash_get
Expand Down Expand Up @@ -291,13 +291,21 @@ def from_any_openapi_schema(cls, schema: Any) -> "ToolSchema":
else None
)

additional_properties_raw = pydash_get(schema, "additionalProperties")
if isinstance(additional_properties_raw, dict):
additional_properties = cls.from_any_openapi_schema(
additional_properties_raw
)
else:
additional_properties = additional_properties_raw

return cls(
type=pydash_get(schema, "type"),
description=pydash_get(schema, "description"),
title=pydash_get(schema, "title"),
properties=properties,
required=pydash_get(schema, "required"),
additional_properties=pydash_get(schema, "additionalProperties"),
additional_properties=additional_properties,
items=items,
min_items=pydash_get(schema, "minItems"),
max_items=pydash_get(schema, "maxItems"),
Expand Down Expand Up @@ -334,7 +342,11 @@ def to_json_schema(self) -> Dict[str, Any]:
if self.required:
result["required"] = self.required
if self.additional_properties is not None:
result["additionalProperties"] = self.additional_properties
result["additionalProperties"] = (
self.additional_properties.to_json_schema()
if isinstance(self.additional_properties, ToolSchema)
else self.additional_properties
)

if self.items:
result["items"] = self.items.to_json_schema()
Expand Down
22 changes: 17 additions & 5 deletions agentrun/toolset/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

from enum import Enum
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Union

from agentrun.utils.model import BaseModel, Field, PageableInput

Expand Down Expand Up @@ -103,7 +103,7 @@ class ToolSchema(BaseModel):
# 对象类型字段
properties: Optional[Dict[str, "ToolSchema"]] = None
required: Optional[List[str]] = None
additional_properties: Optional[bool] = None
additional_properties: Optional[Union[bool, "ToolSchema"]] = None

# 数组类型字段
items: Optional["ToolSchema"] = None
Expand Down Expand Up @@ -137,7 +137,7 @@ def from_any_openapi_schema(cls, schema: Any) -> "ToolSchema":

递归解析所有嵌套结构,保留完整的 schema 信息。
"""
if not schema or not isinstance(schema, dict):
if schema is None or not isinstance(schema, dict):
return cls(type="string")

from pydash import get as pg
Expand Down Expand Up @@ -179,6 +179,14 @@ def from_any_openapi_schema(cls, schema: Any) -> "ToolSchema":
else None
)

additional_properties_raw = pg(schema, "additionalProperties")
if isinstance(additional_properties_raw, dict):
additional_properties = cls.from_any_openapi_schema(
additional_properties_raw
)
else:
additional_properties = additional_properties_raw

return cls(
# 基本字段
type=pg(schema, "type"),
Expand All @@ -187,7 +195,7 @@ def from_any_openapi_schema(cls, schema: Any) -> "ToolSchema":
# 对象类型
properties=properties,
required=pg(schema, "required"),
additional_properties=pg(schema, "additionalProperties"),
additional_properties=additional_properties,
# 数组类型
items=items,
min_items=pg(schema, "minItems"),
Expand Down Expand Up @@ -231,7 +239,11 @@ def to_json_schema(self) -> Dict[str, Any]:
if self.required:
result["required"] = self.required
if self.additional_properties is not None:
result["additionalProperties"] = self.additional_properties
result["additionalProperties"] = (
self.additional_properties.to_json_schema()
if isinstance(self.additional_properties, ToolSchema)
else self.additional_properties
)

# 数组类型
if self.items:
Expand Down
28 changes: 11 additions & 17 deletions tests/e2e/test_workspace_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,16 @@
CredentialListInput,
)
from agentrun.sandbox import Template
from agentrun.sandbox.model import (
PageableInput,
TemplateInput,
TemplateType,
)
from agentrun.sandbox.model import PageableInput, TemplateInput, TemplateType
from agentrun.utils.exception import ResourceNotExistError

WORKSPACE_ID = os.getenv("AGENTRUN_TEST_WORKSPACE_ID")

pytestmark = pytest.mark.skipif(
not WORKSPACE_ID,
reason="AGENTRUN_TEST_WORKSPACE_ID not configured; skipping workspace_id E2E",
reason=(
"AGENTRUN_TEST_WORKSPACE_ID not configured; skipping workspace_id E2E"
),
)


Expand Down Expand Up @@ -98,7 +96,8 @@ async def test_credential_with_workspace_id_async(
)
names = [item.credential_name for item in list_results]
assert credential_name in names, (
f"list(workspace_id={ws!r}) 未返回刚创建的凭证 {credential_name!r},"
f"list(workspace_id={ws!r}) 未返回刚创建的凭证"
f" {credential_name!r},"
f"实际返回 {names!r}"
)
# 列表项的 workspace_id 也应该是同一个
Expand All @@ -112,9 +111,7 @@ async def test_credential_with_workspace_id_async(
except ResourceNotExistError:
pass

def test_credential_with_workspace_id(
self, credential_name: str
):
def test_credential_with_workspace_id(self, credential_name: str):
"""凭证创建时指定 workspace_id,回读与列举均能拿到该 workspace_id"""
client = CredentialClient()
ws = WORKSPACE_ID # type: ignore[assignment]
Expand All @@ -139,20 +136,17 @@ def test_credential_with_workspace_id(
), f"create 返回的 workspace_id 不匹配: {cred.workspace_id!r}"

# 2. get 接口回读 workspace_id
cred_fetched = client.get(
credential_name=credential_name
)
cred_fetched = client.get(credential_name=credential_name)
assert (
cred_fetched.workspace_id == ws
), f"get 返回的 workspace_id 不匹配: {cred_fetched.workspace_id!r}"

# 3. list 接口按 workspace_id 过滤,本次创建的资源应在结果中
list_results = client.list(
CredentialListInput(workspace_id=ws)
)
list_results = client.list(CredentialListInput(workspace_id=ws))
names = [item.credential_name for item in list_results]
assert credential_name in names, (
f"list(workspace_id={ws!r}) 未返回刚创建的凭证 {credential_name!r},"
f"list(workspace_id={ws!r}) 未返回刚创建的凭证"
f" {credential_name!r},"
f"实际返回 {names!r}"
)
# 列表项的 workspace_id 也应该是同一个
Expand Down
Loading
Loading