Skip to content

refactor(core): shared paginateFiltered for client-side-filter listing - #2108

Open
jariy17 wants to merge 1 commit into
refactorfrom
feat/paginate-filtered
Open

refactor(core): shared paginateFiltered for client-side-filter listing#2108
jariy17 wants to merge 1 commit into
refactorfrom
feat/paginate-filtered

Conversation

@jariy17

@jariy17 jariy17 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

One helper for every list that filters a broader API client-side.

Why

Three list* methods over-fetch a broad service API and filter client-side:

What changed

  1. New FilteredPaginator class (src/core/filteredPaginator.ts) — scans full service pages, fills the requested page across them, bounded by 101 scans (ResultTruncationError past that).
  2. listOnlineInsights / listBatchInsights / listGatewayConnectors each delegate to the static FilteredPaginator.paginate({ ... }), passing their predicate + page sizes inline.
  3. Deleted the 3 inline loops + their per-method scan-cap constants.

Behavior changes

  • A page seam can duplicate one item. At a boundary the paginator hands back the scan page's own token, so its matches reappear on the next page (not a re-fetched cursor). Deliberate: it never re-requests a token at a different maxResults, so list APIs that bind maxResults into the token can't reject the continuation.
  • A page may slightly exceed --max-results when one service page already holds a full page of matches (guards against an infinite loop).
  • listGatewayConnectors now validates maxResults (rejects <1 / non-integer) — it didn't before.
  • Net for listBatchInsights + listGatewayConnectors: exact-size pages → dup-on-boundary.

Tests

  • filteredPaginator.test.ts — 10 unit tests: validation, under-fill, overshoot+dup, guard over-return, truncation cap, token seeding, scan sizing.
  • Per-method tests trimmed to filter/wiring only — pagination mechanics now live once in the helper.
  • Full suite 2019 pass / 0 fail, tsc clean.
  • Live bug-bashed on the exploratory account: 5/5 scenarios (list matrix, id-op guard, connector list, batch-insights list, TUI), residue-free.

@github-actions github-actions Bot added the size/xl PR size: XL label Aug 25, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress labels Aug 25, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 25, 2026
@codecov-commenter

codecov-commenter commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.34%. Comparing base (097e1f0) to head (f72cfd2).
⚠️ Report is 2 commits behind head on refactor.

Additional details and impacted files
@@             Coverage Diff              @@
##           refactor    #2108      +/-   ##
============================================
- Coverage     97.38%   97.34%   -0.04%     
============================================
  Files           440      447       +7     
  Lines         26626    27004     +378     
============================================
+ Hits          25929    26287     +358     
- Misses          697      717      +20     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@agentcore-devx-automation agentcore-devx-automation Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AgentCore Harness Review

Verdict: Looks good

Nice consolidation — the three near-identical filter-and-fill pagination loops in eval.tsx (Batch Insights, Online Insights) and gateway.tsx (Gateway Connectors) collapse into paginateFiltered cleanly, and the tests exercise the tricky bits with a real in-memory source rather than mocks.

I walked the algorithm through the interesting cases and it holds up:

  • Normal overshoot (matches from a later scan page push past pageSize): trims to pageSize and returns requestToken — the token that fetched the current page — so the next call re-reads that page and picks up the tail. The boundary match repeats, matching the documented "accepted dup on boundary" contract that the rewritten batchInsights.test.tsx and gateway.test.ts assert.
  • Guard (a single scan page's matches on their own meet pageSize): returns all matches accumulated so far with page.nextToken, so the next call advances past the scan page instead of looping on its own token. Trace on rows("ABCDE")/servicePage=3/pageSize=2 confirms no loop and no lost items across the resumption.
  • Exhaustion returns nextToken: undefined correctly; scan cap at 101 throws ResultTruncationError; scanPageSize undefined passes through as undefined (test at L638-647 verifies).
  • Token stability: fetches only ever happen at scanPageSize (or undefined), never varying maxResults on a re-fetch, so APIs that bind maxResults into their continuation token won't reject the resume.

Behavior changes worth flagging (both look intentional and are captured in the tests):

  1. The guard branch can return more items than maxResults (see paginateFiltered.ts L746-747 and the rewritten online-insight.test.tsx "over-returns a scan page's insight configs when --max-results is smaller"). This is a real UX change from the old boundary-reread approach, which always trimmed exactly. It's the right trade to avoid the self-refilling-token loop, but any downstream consumer that strictly slices by maxResults will now silently drop items on the current page (the extras) rather than see them on the next call. Worth a quick sanity check that no caller does that.
  2. The ResultTruncationError message loses the resource-specific phrasing ("Batch Evaluation scan requests" / "config pages") in favor of a generic "${resourceLabel} discovery exceeded N scans". Fine, just a minor telemetry/observability regression if anything greps those strings.

No new user-facing feature here, so no telemetry expectations. Mocking is appropriate — the helper's tests use a real fake source keyed by offset tokens, and the client tests still stub only the SDK command boundary.

@agentcore-devx-automation agentcore-devx-automation Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Aug 25, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@jariy17
jariy17 marked this pull request as ready for review August 26, 2026 18:17
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
…ine-insight, batch-insight, gateway-connector)
@jariy17
jariy17 force-pushed the feat/paginate-filtered branch from 6b0570e to f72cfd2 Compare August 26, 2026 18:37
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 26, 2026
Comment thread src/core/eval.tsx
throw new ResultTruncationError(
`Batch Insights discovery exceeded ${MAX_BATCH_INSIGHTS_SCAN_REQUESTS} Batch Evaluation scan requests; results are incomplete`,
);
const page = await FilteredPaginator.paginate({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like the design of this

@nborges-aws nborges-aws left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love that we're adding a shared utility for this. A few issues with our filtering algorithm that we should iron out first

if (results.length >= pageSize) {
// Page holds >= pageSize matches by itself. Return every match found (the
// page may exceed maxResults) and advance past it: replaying its token would
// loop, and skipping the surplus would drop matches — so we over-return.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't over returning here just drop resources then? We only render up to pageSize rows, but we continue from where the service token leaves off. Everything beyond maxResults that was included by the service becomes permanently unreachable.

@jariy17 jariy17 Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is best case scenario. It's not the best solution we can find. We can generate a composite token ({ serviceToken, skip }) so we can prevent this and the replay issue but its too complicated for a small inconvenience.

if (matches.length >= pageSize) {
return { items: results, nextToken: page.nextToken };
}
// Partial page: replaying its token is safe — the taken matches just repeat.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get how replaying the service page here prevents dropping matched items. But for the inverse case, wouldn't this duplicate every match already consumed from the first partial page? If page A matches 2 items and page B matches 8, we're still using the token that returns page B. So all 8 from the second page would be duplicated and rendered twice.

I think this needs to change so that if A + B fills the max results, we return nextToken?

@jariy17 jariy17 Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is best case scenario without introduce a composite token. I think its fine customers seen a duplicate. If this is an issue, I can introduce now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants