fix: Fix slow list endpoints for object oriented sdk#767
Conversation
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
✅ Object Smoke Tests & Coverage ReportTest Results✅ All smoke tests passed Coverage Results
Coverage Requirement: 100% function coverage (all public methods must be called in smoke tests) ✅ All tests passed and all object methods are covered! View detailed coverage report
|
| const page = await this.client.axons.list(params, options); | ||
| const axons: Axon[] = []; | ||
| for await (const axon of result) { | ||
| for (const axon of page.getPaginatedItems()) { |
There was a problem hiding this comment.
Suggestion: This change breaks the documented behavior of listing all items when no pagination limit is provided: it now always returns only the first page. Preserve full auto-pagination when limit is not explicitly set, and only use getPaginatedItems() for the single-page path when a limit is provided. [logic error]
Severity Level: Major ⚠️
- ❌ Axon listing without limit returns incomplete results.
- ⚠️ Existing code examples suggest full list is expected.
- ⚠️ Any bulk axon operations may silently skip items.| const page = await this.client.axons.list(params, options); | |
| const axons: Axon[] = []; | |
| for await (const axon of result) { | |
| for (const axon of page.getPaginatedItems()) { | |
| const axons: Axon[] = []; | |
| if (params?.limit !== undefined) { | |
| const page = await this.client.axons.list(params, options); | |
| for (const axon of page.getPaginatedItems()) { | |
| axons.push(Axon.fromId(this.client, axon.id)); | |
| } | |
| } else { | |
| for await (const axon of this.client.axons.list(params, options)) { | |
| axons.push(Axon.fromId(this.client, axon.id)); | |
| } | |
| } |
Steps of Reproduction ✅
1. Import and instantiate the SDK client as shown in `src/sdk.ts` RunloopSDK class (e.g.,
`const runloop = new RunloopSDK();`).
2. Call the AxonOps list method without a limit via `runloop.axon.list()` (AxonOps is
defined in `src/sdk.ts` under the `[Beta] Axon SDK interface for managing axons` section,
and its `list` implementation uses `const page = await this.client.axons.list(params,
options);` followed by `for (const axon of page.getPaginatedItems()) { ... }` at lines
1580–1582 in the PR hunk).
3. Ensure the underlying API has more axons than fit on a single page (the API client
`this.client.axons.list` is a paginated endpoint as implied by `getPaginatedItems()` and
the PR description about auto-pagination).
4. Observe that `runloop.axon.list()` returns only the items from the first page because
it iterates `page.getPaginatedItems()` for a single page, whereas prior behavior
(described in the PR text and other list implementations like `AgentOps.list` and
`ScorerOps.list` in `src/sdk.ts`) auto-paginated across all pages when no `limit` was
provided.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** src/sdk.ts
**Line:** 1580:1582
**Comment:**
*Logic Error: This change breaks the documented behavior of listing all items when no pagination limit is provided: it now always returns only the first page. Preserve full auto-pagination when `limit` is not explicitly set, and only use `getPaginatedItems()` for the single-page path when a `limit` is provided.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.| const page = await client.agents.list(params, options); | ||
| const result: Agent[] = []; | ||
|
|
||
| for await (const agent of agents) { | ||
| for (const agent of page.getPaginatedItems()) { |
There was a problem hiding this comment.
Suggestion: This change breaks the previous list() contract by always returning only the first page, even when no limit is provided. Callers using runloop.agent.list() to fetch all agents will now silently get partial results. Keep first-page behavior only when limit is explicitly set, and preserve auto-pagination otherwise. [logic error]
Severity Level: Major ⚠️
- ❌ Object-oriented `Agent.list` no longer returns all agents.
- ⚠️ Callers expecting full auto-pagination get partial results.
- ⚠️ Downstream features assuming complete agent set may misbehave.| const page = await client.agents.list(params, options); | |
| const result: Agent[] = []; | |
| for await (const agent of agents) { | |
| for (const agent of page.getPaginatedItems()) { | |
| const result: Agent[] = []; | |
| if (params?.limit !== undefined) { | |
| const page = await client.agents.list(params, options); | |
| for (const agent of page.getPaginatedItems()) { | |
| result.push(new Agent(client, agent.id)); | |
| } | |
| } else { | |
| for await (const agent of client.agents.list(params, options)) { | |
| result.push(new Agent(client, agent.id)); | |
| } |
Steps of Reproduction ✅
1. In a consumer project using this SDK, call `runloop.agent.list()` **without** passing a
`limit` parameter, which routes to `Agent.list(client, params?, options?)` in
`src/sdk/agent.ts:114-127` (final file state).
2. Inside `Agent.list`, the code at `src/sdk/agent.ts:119` executes `const page = await
client.agents.list(params, options);`, obtaining only the first page of results from the
underlying `client.agents.list` paginator.
3. The subsequent loop at `src/sdk/agent.ts:122-123` iterates `for (const agent of
page.getPaginatedItems())`, which, per the PR description, returns only items from that
single page rather than auto-paginating through all pages.
4. The function returns `result` at `src/sdk/agent.ts:126`, containing only the first page
of agents; any existing caller that previously relied on `runloop.agent.list()` to
auto-paginate and return all agents now silently receives a truncated list instead of the
complete set.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** src/sdk/agent.ts
**Line:** 119:122
**Comment:**
*Logic Error: This change breaks the previous `list()` contract by always returning only the first page, even when no `limit` is provided. Callers using `runloop.agent.list()` to fetch all agents will now silently get partial results. Keep first-page behavior only when `limit` is explicitly set, and preserve auto-pagination otherwise.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.|
CodeAnt AI finished reviewing your PR. |
Port verification and testing from TypeScript PR #767 which fixed slow list endpoints that were auto-paginating through all pages. ## Analysis Results The Python SDK does NOT suffer from the bug that affected TypeScript because: - Python implementation uses direct property access (`page.items`) - TypeScript was using async iteration (`for await`) which auto-paginated - Our existing unit tests already used correct mocking patterns ## What Was Added New smoke tests in `tests/smoketests/sdk/test_list_pagination.py`: - 28 comprehensive tests (15 async, 13 sync) - Tests all 13 resource types (agents, devboxes, blueprints, etc.) - Verifies `list(limit=N)` returns at most N items - Ensures no auto-pagination occurs - Includes data creation test to verify with actual API calls ## Verification All SDK list methods verified correct: ✅ AsyncDevboxOps.list() - accesses page.devboxes ✅ AsyncSnapshotOps.list() - accesses page.snapshots ✅ AsyncBlueprintOps.list() - accesses page.blueprints ✅ AsyncStorageObjectOps.list() - accesses page.objects ✅ AsyncAxonOps.list() - accesses result.axons ✅ AsyncScorerOps.list() - accesses page.scorers ✅ AsyncAgentOps.list() - accesses page.agents ✅ AsyncScenarioOps.list() - accesses page.scenarios ✅ AsyncBenchmarkOps.list() - accesses page.benchmarks ✅ AsyncNetworkPolicyOps.list() - accesses page.network_policies ✅ AsyncGatewayConfigOps.list() - accesses page.gateway_configs ✅ AsyncMcpConfigOps.list() - accesses page.mcp_configs ✅ AsyncSecretOps.list() - accesses result.secrets (+ all sync equivalents) ## Benefits ✅ Faster list results - only fetches requested page ✅ Fewer API requests - no unnecessary pagination ✅ Better resource usage - respects limit parameter ✅ Documented behavior - tests serve as specification ✅ Regression prevention - ensures future changes maintain correctness ## Related - TypeScript PR: runloopai/api-client-ts#767 - Detailed analysis: PR_767_PORT_SUMMARY.md - Code comparison: IMPLEMENTATION_COMPARISON.md - Quick reference: PR_767_PORT.md ## Testing Run the new tests: ```bash uv run pytest tests/smoketests/sdk/test_list_pagination.py -v ``` No source code changes required - Python implementation already correct.
User description
All the SDK list() methods use for await to iterate over paginated results, which auto-paginates through ALL pages regardless of the limit parameter you pass
For example, when you call
sdk.gatewayConfig.list({ limit: 10 }):CodeAnt-AI Description
List calls now respect the requested page size and stop fetching after the first page
What Changed
Impact
✅ Faster list results✅ Fewer unnecessary API requests✅ Better handling of limited list views💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.