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: 2 additions & 2 deletions agentrun/integration/utils/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1562,8 +1562,8 @@ def _build_openapi_schema(
if isinstance(schema, dict):
properties[name] = {
**schema,
"description": (
param.get("description") or schema.get("description", "")
"description": param.get("description") or schema.get(
"description", ""
),
}
if param.get("required"):
Expand Down
6 changes: 5 additions & 1 deletion agentrun/sandbox/__sandbox_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
Union,
)

from pydantic import Field

from agentrun.sandbox.model import TemplateType
from agentrun.utils.config import Config
from agentrun.utils.model import BaseModel
Expand Down Expand Up @@ -56,7 +58,9 @@ class Sandbox(BaseModel):
"""沙箱全局唯一资源名称 / Sandbox ARN"""
sandbox_id: Optional[str] = None
"""沙箱 ID / Sandbox ID"""
sandbox_idle_ttlin_seconds: Optional[int] = None
sandbox_idle_ttlin_seconds: Optional[int] = Field(
None, alias="sandboxIdleTTLInSeconds"
)
"""沙箱空闲 TTL(秒) / Sandbox Idle TTL (seconds)"""
sandbox_idle_timeout_seconds: Optional[int] = None
"""沙箱空闲超时时间(秒) / Sandbox Idle Timeout (seconds)"""
Expand Down
6 changes: 5 additions & 1 deletion agentrun/sandbox/__template_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

from typing import Dict, List, Optional

from pydantic import Field

from agentrun.sandbox.model import (
PageableInput,
TemplateContainerConfiguration,
Expand Down Expand Up @@ -52,7 +54,9 @@ class Template(BaseModel):
"""执行角色 ARN / Execution Role ARN"""
sandbox_idle_timeout_in_seconds: Optional[int] = None
"""沙箱空闲超时时间(秒) / Sandbox Idle Timeout (seconds)"""
sandbox_ttlin_seconds: Optional[int] = None
sandbox_ttlin_seconds: Optional[int] = Field(
None, alias="sandboxTTLInSeconds"
)
"""沙箱存活时间(秒) / Sandbox TTL (seconds)"""
share_concurrency_limit_per_sandbox: Optional[int] = None
"""每个沙箱的最大并发会话数 / Max Concurrency Limit Per Sandbox"""
Expand Down
6 changes: 4 additions & 2 deletions agentrun/sandbox/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any, Dict, List, Optional, TYPE_CHECKING
import uuid

from pydantic import model_validator
from pydantic import Field, model_validator

from agentrun.utils.model import BaseModel

Expand Down Expand Up @@ -264,7 +264,9 @@ class TemplateInput(BaseModel):
"""执行角色 ARN / Execution Role ARN"""
sandbox_idle_timeout_in_seconds: Optional[int] = 1800
"""沙箱空闲超时时间(秒) / Sandbox Idle Timeout (seconds)"""
sandbox_ttlin_seconds: Optional[int] = 21600
sandbox_ttlin_seconds: Optional[int] = Field(
21600, alias="sandboxTTLInSeconds"
)
"""沙箱存活时间(秒) / Sandbox TTL (seconds)"""
share_concurrency_limit_per_sandbox: Optional[int] = 200
"""每个沙箱的最大并发会话数 / Max Concurrency Limit Per Sandbox"""
Expand Down
6 changes: 5 additions & 1 deletion agentrun/sandbox/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
Union,
)

from pydantic import Field

from agentrun.sandbox.model import TemplateType
from agentrun.utils.config import Config
from agentrun.utils.model import BaseModel
Expand Down Expand Up @@ -66,7 +68,9 @@ class Sandbox(BaseModel):
"""沙箱全局唯一资源名称 / Sandbox ARN"""
sandbox_id: Optional[str] = None
"""沙箱 ID / Sandbox ID"""
sandbox_idle_ttlin_seconds: Optional[int] = None
sandbox_idle_ttlin_seconds: Optional[int] = Field(
None, alias="sandboxIdleTTLInSeconds"
)
"""沙箱空闲 TTL(秒) / Sandbox Idle TTL (seconds)"""
sandbox_idle_timeout_seconds: Optional[int] = None
"""沙箱空闲超时时间(秒) / Sandbox Idle Timeout (seconds)"""
Expand Down
6 changes: 5 additions & 1 deletion agentrun/sandbox/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

from typing import Dict, List, Optional

from pydantic import Field

from agentrun.sandbox.model import (
PageableInput,
TemplateContainerConfiguration,
Expand Down Expand Up @@ -62,7 +64,9 @@ class Template(BaseModel):
"""执行角色 ARN / Execution Role ARN"""
sandbox_idle_timeout_in_seconds: Optional[int] = None
"""沙箱空闲超时时间(秒) / Sandbox Idle Timeout (seconds)"""
sandbox_ttlin_seconds: Optional[int] = None
sandbox_ttlin_seconds: Optional[int] = Field(
None, alias="sandboxTTLInSeconds"
)
"""沙箱存活时间(秒) / Sandbox TTL (seconds)"""
share_concurrency_limit_per_sandbox: Optional[int] = None
"""每个沙箱的最大并发会话数 / Max Concurrency Limit Per Sandbox"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -664,9 +664,7 @@ async def invoke_agent(request: AgentRequest):
json={
"messages": [{
"role": "user",
"content": (
"查询当前的时间,并获取天气信息,同时输出我的密钥信息"
),
"content": "查询当前的时间,并获取天气信息,同时输出我的密钥信息",
}],
"stream": True,
},
Expand Down Expand Up @@ -729,9 +727,7 @@ async def invoke_agent(request: AgentRequest):
json={
"messages": [{
"role": "user",
"content": (
"查询当前的时间,并获取天气信息,同时输出我的密钥信息"
),
"content": "查询当前的时间,并获取天气信息,同时输出我的密钥信息",
}],
"stream": True,
},
Expand Down
20 changes: 5 additions & 15 deletions tests/unittests/toolset/api/test_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,7 @@ def test_post_with_ref_schema(self):
"content": {
"application/json": {
"schema": {
"$ref": (
"#/components/schemas/CreateOrderRequest"
)
"$ref": "#/components/schemas/CreateOrderRequest"
}
}
},
Expand Down Expand Up @@ -758,9 +756,7 @@ def test_invalid_ref_gracefully_handled(self):
"content": {
"application/json": {
"schema": {
"$ref": (
"#/components/schemas/NonExistent"
)
"$ref": "#/components/schemas/NonExistent"
}
}
}
Expand Down Expand Up @@ -793,9 +789,7 @@ def test_external_ref_not_resolved(self):
"content": {
"application/json": {
"schema": {
"$ref": (
"https://example.com/schemas/external.json"
)
"$ref": "https://example.com/schemas/external.json"
}
}
}
Expand Down Expand Up @@ -915,9 +909,7 @@ def _get_coffee_shop_schema():
"content": {
"application/json": {
"schema": {
"$ref": (
"#/components/schemas/CreateOrderRequest"
)
"$ref": "#/components/schemas/CreateOrderRequest"
}
}
},
Expand Down Expand Up @@ -953,9 +945,7 @@ def _get_coffee_shop_schema():
"content": {
"application/json": {
"schema": {
"$ref": (
"#/components/schemas/UpdateOrderStatusRequest"
)
"$ref": "#/components/schemas/UpdateOrderStatusRequest"
}
}
},
Expand Down
78 changes: 78 additions & 0 deletions tests/unittests/utils/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,81 @@ def test_is_final_instance_method(self):
"""测试实例方法 is_final"""
assert Status.READY.is_final() is True
assert Status.CREATING.is_final() is False


class TestTTLAliasFixIssue53:
"""测试 TTL 字段的显式 alias 修复 (Issue #53)

验证含有连续大写缩写词 (TTL) 的字段能正确从 API 返回的 camelCase key 解析。
"""

def test_template_sandbox_ttlin_seconds_from_api_data(self):
"""Template.sandbox_ttlin_seconds 应能通过 sandboxTTLInSeconds 正确解析"""
from agentrun.sandbox.template import Template

api_data = {
"templateName": "code-interpreter-01",
"sandboxIdleTimeoutInSeconds": 900,
"sandboxTTLInSeconds": 3600,
}
t = Template.model_validate(api_data, by_alias=True)
assert t.sandbox_idle_timeout_in_seconds == 900
assert t.sandbox_ttlin_seconds == 3600
assert t.model_extra.get("sandboxTTLInSeconds") is None

def test_template_sandbox_ttlin_seconds_by_field_name(self):
"""Template.sandbox_ttlin_seconds 也应支持通过字段名直接赋值"""
from agentrun.sandbox.template import Template

t = Template(sandbox_ttlin_seconds=1800)
assert t.sandbox_ttlin_seconds == 1800

def test_template_sandbox_ttlin_seconds_serialization(self):
"""Template 序列化时应使用正确的 alias sandboxTTLInSeconds"""
from agentrun.sandbox.template import Template

t = Template(sandbox_ttlin_seconds=7200)
data = t.model_dump(by_alias=True)
assert data["sandboxTTLInSeconds"] == 7200

def test_template_input_sandbox_ttlin_seconds_serialization(self):
"""TemplateInput.sandbox_ttlin_seconds 序列化应使用 sandboxTTLInSeconds"""
from agentrun.sandbox.model import TemplateInput, TemplateType

inp = TemplateInput(
template_type=TemplateType.CODE_INTERPRETER,
sandbox_ttlin_seconds=600,
)
data = inp.model_dump(by_alias=True)
assert data["sandboxTTLInSeconds"] == 600

def test_sandbox_idle_ttlin_seconds_from_api_data(self):
"""Sandbox.sandbox_idle_ttlin_seconds 应能通过 sandboxIdleTTLInSeconds 正确解析"""
from agentrun.sandbox.sandbox import Sandbox

api_data = {
"sandboxId": "sb-123",
"sandboxIdleTTLInSeconds": 300,
"sandboxIdleTimeoutSeconds": 600,
}
s = Sandbox.model_validate(api_data, by_alias=True)
assert s.sandbox_idle_ttlin_seconds == 300
assert s.sandbox_idle_timeout_seconds == 600
assert s.model_extra.get("sandboxIdleTTLInSeconds") is None

def test_template_from_inner_object_with_ttl(self):
"""Template.from_inner_object 应正确解析 sandboxTTLInSeconds"""
from agentrun.sandbox.template import Template

class MockDaraModel:

def to_map(self):
return {
"templateName": "test-template",
"sandboxIdleTimeoutInSeconds": 900,
"sandboxTTLInSeconds": 3600,
}

t = Template.from_inner_object(MockDaraModel())
assert t.sandbox_ttlin_seconds == 3600
assert t.sandbox_idle_timeout_in_seconds == 900
Loading