Skip to content

fix(metrics): return real total memory count instead of capped page size#1674

Open
Sanjays2402 wants to merge 2 commits intoMemTensor:mainfrom
Sanjays2402:fix/issue-1593
Open

fix(metrics): return real total memory count instead of capped page size#1674
Sanjays2402 wants to merge 2 commits intoMemTensor:mainfrom
Sanjays2402:fix/issue-1593

Conversation

@Sanjays2402
Copy link
Copy Markdown

Summary

The Web UI memory-count card on the Memories page was stuck at 500 even when the database held 1400+ traces (#1593). The metrics path counted items from an already-limited listing instead of running a dedicated COUNT query.

Root cause

countTraces in apps/memos-local-plugin/core/pipeline/memory-core.ts computed the total by calling handle.repos.traces.list({ limit: 100_000 }) and reading rows.length. The shared helper buildPageClauses / clampLimit (in core/storage/repos/_helpers.ts) silently clamps every list limit to 500, so list({ limit: 100_000 }) actually returns at most 500 rows. The resulting rows.length (or grouped turnKeys.size) was therefore capped at 500 regardless of how many traces existed.

The /api/v1/traces endpoint uses countTraces, and the Memories view (web/src/views/MemoriesView.tsx) renders that response's total in its pagination footer, so the Web UI showed 500 forever.

Fix

In countTraces:

  • For the no-search path, use the repo's dedicated SELECT COUNT(*) queries directly (repos.traces.count / countTurns). These don't go through buildPageClauses and have no 500-row cap, so the returned total reflects the real database size.
  • For the substring-search path, page through traces explicitly with offset increments instead of relying on a single list() call (which would also be clamped at 500). Each batch is filtered for visibility and matched against the search needle, so the count stays accurate even above 500 rows.

Listings keep their existing page-size limits; only the count was wrong.

Verification

Added a regression test in tests/unit/pipeline/memory-core.test.ts that inserts 600 trace rows across 6 distinct turns and asserts:

  • countTraces({}) returns 600 (was 500 before the fix)
  • countTraces({ groupByTurn: true }) returns 6 (was capped at the smaller of 6 or 500 before; would break for >500 turns)

Files changed:

  • apps/memos-local-plugin/core/pipeline/memory-core.ts (~34 net lines)
  • apps/memos-local-plugin/tests/unit/pipeline/memory-core.test.ts (regression test)

Fixes #1593

The Web UI memory-count card on the Memories page was stuck at 500
even when the database held 1400+ traces. `countTraces` was counting
rows returned by `repos.traces.list({ limit: 100_000 })`, but the
shared `buildPageClauses`/`clampLimit` helper silently clamps every
list `limit` to 500. The result was that `countTraces` returned at
most 500 regardless of how many traces actually existed.

Switch `countTraces` to use the repo's dedicated SELECT COUNT(*)
queries (`repos.traces.count` / `countTurns`), which have no
page-size cap, so the displayed total reflects the real database size.
The substring-search path now pages through traces explicitly so it
also accurately counts results above the 500-row cap. Listings keep
their page-size limits; only the count was wrong.

Adds a regression test that inserts 600 trace rows across 6 turns and
verifies both `countTraces({})` and `countTraces({ groupByTurn: true })`
return the real total instead of being clamped at 500.

Fixes MemTensor#1593
Copilot AI review requested due to automatic review settings May 9, 2026 19:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes an incorrect “total memories” count in the memos-local-plugin metrics path where totals were capped at 500 due to repo list pagination clamping, causing the Web UI Memories count to get stuck at 500 (issue #1593).

Changes:

  • Updated countTraces to use repo-level COUNT queries when no substring search is provided, avoiding the list() 500-row cap.
  • Updated substring-search counting to page through trace listings in batches so counts can exceed 500.
  • Added a regression unit test that inserts 600 traces and validates both raw-trace and group-by-turn totals.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
apps/memos-local-plugin/core/pipeline/memory-core.ts Fixes countTraces total counting logic to avoid the 500-row clamp (COUNT queries + explicit paging for search).
apps/memos-local-plugin/tests/unit/pipeline/memory-core.test.ts Adds regression coverage ensuring totals are correct when trace rows exceed 500.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2639 to +2642
// cap, so they return the actual total.
return input?.groupByTurn
? handle.repos.traces.countTurns({ sessionId: input?.sessionId })
: handle.repos.traces.count({ sessionId: input?.sessionId });
Address Copilot review on MemTensor#1674: the new COUNT path bypassed the
visibility predicate that list() applies, so countTraces could return
totals that included rows owned by other profiles/namespaces. This
broke pagination math and risked leaking the existence of cross-profile
data through the visible count.

Wire the same visibility WHERE clause into the count and countTurns
methods (sharing a single buildVisibilityClause helper with list() to
keep the predicate authoritative in one place), and pass the relevant
options through countTraces in memory-core. Extend the runtime
visibilityWhere() SQL fragment to match isVisibleTo() exactly,
including the legacy unknown/default-owner branch so pushing the
predicate into SQL doesn't silently drop pre-namespace seed rows.

Regression test: insert traces under two profiles and assert each
profile's countTraces returns only its own rows.
@Sanjays2402
Copy link
Copy Markdown
Author

Real catch — addressed in the latest commit. The new COUNT path was bypassing the visibility predicate that list() applies, so totals could include rows from other profiles/namespaces and break pagination math.

Fix: shared buildVisibilityClause helper used by both list() and the count methods, so the predicate stays authoritative in one place. countTraces in memory-core.ts now threads the relevant options through. Added a regression test that inserts traces under two profiles and asserts each profile's countTraces returns only its own count.

@CaralHsi CaralHsi requested a review from hijzy May 11, 2026 02:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web UI memory count stuck at 500, actual traces exceed 1400

2 participants