Skip to content

Commit 0d30c32

Browse files
authored
Merge pull request #37 from Serverless-Devs/fix-list-endpoints
feat(endpoint): implement pagination methods for AgentRuntimeEndpoint
2 parents 18064dc + 451b114 commit 0d30c32

File tree

3 files changed

+231
-0
lines changed

3 files changed

+231
-0
lines changed

agentrun/agent_runtime/__endpoint_async_template.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
AgentRuntimeEndpointUpdateInput,
1919
)
2020
from agentrun.utils.config import Config
21+
from agentrun.utils.model import PageableInput
2122
from agentrun.utils.resource import ResourceBase
2223

2324

@@ -160,6 +161,45 @@ async def get_by_id_async(
160161
config=config,
161162
)
162163

164+
@classmethod
165+
async def _list_page_async(
166+
cls,
167+
page_input: PageableInput,
168+
config: Optional[Config] = None,
169+
**kwargs,
170+
) -> List["AgentRuntimeEndpoint"]:
171+
"""分页列出端点 / List endpoints by page
172+
173+
此方法是 ResourceBase 要求实现的抽象方法,用于支持分页查询。
174+
This method is an abstract method required by ResourceBase to support pagination.
175+
176+
Args:
177+
page_input: 分页参数 / Pagination parameters
178+
config: 配置对象,可选 / Configuration object, optional
179+
**kwargs: 其他参数,必须包含 agent_runtime_id / Other parameters, must include agent_runtime_id
180+
181+
Returns:
182+
List[AgentRuntimeEndpoint]: 端点对象列表 / List of endpoint objects
183+
184+
Raises:
185+
ValueError: 当 agent_runtime_id 未提供时 / When agent_runtime_id is not provided
186+
HTTPError: HTTP 请求错误 / HTTP request error
187+
"""
188+
agent_runtime_id = kwargs.get("agent_runtime_id")
189+
if not agent_runtime_id:
190+
raise ValueError(
191+
"agent_runtime_id is required for listing endpoints"
192+
)
193+
194+
return await cls.__get_client().list_endpoints_async(
195+
agent_runtime_id,
196+
AgentRuntimeEndpointListInput(
197+
page_number=page_input.page_number,
198+
page_size=page_input.page_size,
199+
),
200+
config=config,
201+
)
202+
163203
@classmethod
164204
async def list_by_id_async(
165205
cls, agent_runtime_id: str, config: Optional[Config] = None

agentrun/agent_runtime/endpoint.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
AgentRuntimeEndpointUpdateInput,
2929
)
3030
from agentrun.utils.config import Config
31+
from agentrun.utils.model import PageableInput
3132
from agentrun.utils.resource import ResourceBase
3233

3334

@@ -286,6 +287,84 @@ def get_by_id(
286287
config=config,
287288
)
288289

290+
@classmethod
291+
async def _list_page_async(
292+
cls,
293+
page_input: PageableInput,
294+
config: Optional[Config] = None,
295+
**kwargs,
296+
) -> List["AgentRuntimeEndpoint"]:
297+
"""分页列出端点 / List endpoints by page
298+
299+
此方法是 ResourceBase 要求实现的抽象方法,用于支持分页查询。
300+
This method is an abstract method required by ResourceBase to support pagination.
301+
302+
Args:
303+
page_input: 分页参数 / Pagination parameters
304+
config: 配置对象,可选 / Configuration object, optional
305+
**kwargs: 其他参数,必须包含 agent_runtime_id / Other parameters, must include agent_runtime_id
306+
307+
Returns:
308+
List[AgentRuntimeEndpoint]: 端点对象列表 / List of endpoint objects
309+
310+
Raises:
311+
ValueError: 当 agent_runtime_id 未提供时 / When agent_runtime_id is not provided
312+
HTTPError: HTTP 请求错误 / HTTP request error
313+
"""
314+
agent_runtime_id = kwargs.get("agent_runtime_id")
315+
if not agent_runtime_id:
316+
raise ValueError(
317+
"agent_runtime_id is required for listing endpoints"
318+
)
319+
320+
return await cls.__get_client().list_endpoints_async(
321+
agent_runtime_id,
322+
AgentRuntimeEndpointListInput(
323+
page_number=page_input.page_number,
324+
page_size=page_input.page_size,
325+
),
326+
config=config,
327+
)
328+
329+
@classmethod
330+
def _list_page(
331+
cls,
332+
page_input: PageableInput,
333+
config: Optional[Config] = None,
334+
**kwargs,
335+
) -> List["AgentRuntimeEndpoint"]:
336+
"""分页列出端点 / List endpoints by page
337+
338+
此方法是 ResourceBase 要求实现的抽象方法,用于支持分页查询。
339+
This method is an abstract method required by ResourceBase to support pagination.
340+
341+
Args:
342+
page_input: 分页参数 / Pagination parameters
343+
config: 配置对象,可选 / Configuration object, optional
344+
**kwargs: 其他参数,必须包含 agent_runtime_id / Other parameters, must include agent_runtime_id
345+
346+
Returns:
347+
List[AgentRuntimeEndpoint]: 端点对象列表 / List of endpoint objects
348+
349+
Raises:
350+
ValueError: 当 agent_runtime_id 未提供时 / When agent_runtime_id is not provided
351+
HTTPError: HTTP 请求错误 / HTTP request error
352+
"""
353+
agent_runtime_id = kwargs.get("agent_runtime_id")
354+
if not agent_runtime_id:
355+
raise ValueError(
356+
"agent_runtime_id is required for listing endpoints"
357+
)
358+
359+
return cls.__get_client().list_endpoints(
360+
agent_runtime_id,
361+
AgentRuntimeEndpointListInput(
362+
page_number=page_input.page_number,
363+
page_size=page_input.page_size,
364+
),
365+
config=config,
366+
)
367+
289368
@classmethod
290369
async def list_by_id_async(
291370
cls, agent_runtime_id: str, config: Optional[Config] = None

tests/unittests/agent_runtime/test_endpoint.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,115 @@ def test_invoke_openai(self, mock_client_class, mock_data_api_class):
468468
def test_invoke_openai_async(self, mock_client_class, mock_data_api_class):
469469
"""测试 invoke_openai_async - 跳过因为私有属性问题"""
470470
pass
471+
472+
473+
class TestAgentRuntimeEndpointAbstractMethods:
474+
"""测试 AgentRuntimeEndpoint 抽象方法实现
475+
476+
此测试类用于验证 AgentRuntimeEndpoint 正确实现了 ResourceBase 要求的抽象方法。
477+
这是为了防止类似于 Issue #XXX 的问题再次发生,确保 from_inner_object 能够正常实例化对象。
478+
"""
479+
480+
def test_from_inner_object_instantiation(self):
481+
"""测试 from_inner_object 能够正常实例化对象
482+
483+
这个测试确保 AgentRuntimeEndpoint 类实现了所有必需的抽象方法。
484+
如果抽象方法未实现,from_inner_object 会抛出 TypeError。
485+
"""
486+
487+
# 准备一个最小的有效数据
488+
class MockDaraModel:
489+
490+
def to_map(self):
491+
return {
492+
"agentRuntimeEndpointId": "are-test-123",
493+
"agentRuntimeEndpointName": "test-endpoint",
494+
"agentRuntimeId": "ar-test-123",
495+
"status": "READY",
496+
}
497+
498+
inner_obj = MockDaraModel()
499+
500+
# 这里不应该抛出 TypeError: Can't instantiate abstract class
501+
endpoint = AgentRuntimeEndpoint.from_inner_object(inner_obj)
502+
503+
# 验证对象正确创建
504+
assert endpoint is not None
505+
assert endpoint.agent_runtime_endpoint_id == "are-test-123"
506+
assert endpoint.agent_runtime_endpoint_name == "test-endpoint"
507+
508+
def test_list_page_method_exists(self):
509+
"""测试 _list_page 方法存在且可调用"""
510+
# 验证类有 _list_page 方法
511+
assert hasattr(AgentRuntimeEndpoint, "_list_page")
512+
assert callable(getattr(AgentRuntimeEndpoint, "_list_page"))
513+
514+
def test_list_page_async_method_exists(self):
515+
"""测试 _list_page_async 方法存在且可调用"""
516+
# 验证类有 _list_page_async 方法
517+
assert hasattr(AgentRuntimeEndpoint, "_list_page_async")
518+
assert callable(getattr(AgentRuntimeEndpoint, "_list_page_async"))
519+
520+
@patch(CLIENT_PATH)
521+
def test_list_page_requires_agent_runtime_id(self, mock_client_class):
522+
"""测试 _list_page 需要 agent_runtime_id 参数"""
523+
from agentrun.utils.model import PageableInput
524+
525+
# 不提供 agent_runtime_id 应该抛出 ValueError
526+
with pytest.raises(ValueError, match="agent_runtime_id is required"):
527+
AgentRuntimeEndpoint._list_page(
528+
PageableInput(page_number=1, page_size=10)
529+
)
530+
531+
@patch(CLIENT_PATH)
532+
def test_list_page_async_requires_agent_runtime_id(self, mock_client_class):
533+
"""测试 _list_page_async 需要 agent_runtime_id 参数"""
534+
from agentrun.utils.model import PageableInput
535+
536+
# 不提供 agent_runtime_id 应该抛出 ValueError
537+
with pytest.raises(ValueError, match="agent_runtime_id is required"):
538+
asyncio.run(
539+
AgentRuntimeEndpoint._list_page_async(
540+
PageableInput(page_number=1, page_size=10)
541+
)
542+
)
543+
544+
@patch(CLIENT_PATH)
545+
def test_list_page_with_agent_runtime_id(self, mock_client_class):
546+
"""测试 _list_page 正确传递 agent_runtime_id"""
547+
from agentrun.utils.model import PageableInput
548+
549+
mock_client = MagicMock()
550+
mock_client.list_endpoints.return_value = []
551+
mock_client_class.return_value = mock_client
552+
553+
# 提供 agent_runtime_id 应该正常执行
554+
result = AgentRuntimeEndpoint._list_page(
555+
PageableInput(page_number=1, page_size=10),
556+
agent_runtime_id="ar-test-123",
557+
)
558+
559+
# 验证调用了 list_endpoints
560+
mock_client.list_endpoints.assert_called_once()
561+
assert result == []
562+
563+
@patch(CLIENT_PATH)
564+
def test_list_page_async_with_agent_runtime_id(self, mock_client_class):
565+
"""测试 _list_page_async 正确传递 agent_runtime_id"""
566+
from agentrun.utils.model import PageableInput
567+
568+
mock_client = MagicMock()
569+
mock_client.list_endpoints_async = AsyncMock(return_value=[])
570+
mock_client_class.return_value = mock_client
571+
572+
# 提供 agent_runtime_id 应该正常执行
573+
result = asyncio.run(
574+
AgentRuntimeEndpoint._list_page_async(
575+
PageableInput(page_number=1, page_size=10),
576+
agent_runtime_id="ar-test-123",
577+
)
578+
)
579+
580+
# 验证调用了 list_endpoints_async
581+
mock_client.list_endpoints_async.assert_called_once()
582+
assert result == []

0 commit comments

Comments
 (0)