Skip to content

fix: delete stale vectors when clearing messages#1152

Merged
omeraplak merged 3 commits intomainfrom
fix/memory-clear-vectors-1148
Mar 15, 2026
Merged

fix: delete stale vectors when clearing messages#1152
omeraplak merged 3 commits intomainfrom
fix/memory-clear-vectors-1148

Conversation

@omeraplak
Copy link
Member

@omeraplak omeraplak commented Mar 15, 2026

PR Checklist

Please check if your PR fulfills the following requirements:

Bugs / Features

What is the current behavior?

When Memory.clearMessages() is used with semantic memory enabled, the conversation messages are removed from storage but the vector entries remain in the vector store. That allows semantic search to keep returning cleared conversation content.

What is the new behavior?

Memory.clearMessages() now deletes the related vector entries before clearing message storage. This keeps semantic search results in sync with message deletion for both conversation-scoped clears and user-scoped clears.

fixes #1148

Notes for reviewers

  • Added a regression test in packages/core/src/memory/semantic-search.spec.ts
  • Verified with pnpm --dir packages/core exec vitest run src/memory/semantic-search.spec.ts
  • Reproduced locally against examples/base before the fix and confirmed semantic search results are removed after the fix

Summary by cubic

Memory.clearMessages() now deletes related vector entries before removing messages and handles storage pagination so user-wide cleanup covers all conversations. Fixes #1148.

  • Bug Fixes
    • Deletes vectors via deleteBatch for conversation clears and user-wide clears across storage pages in @voltagent/core.
    • Adds tests for paginated user-wide and single-conversation clears to ensure vectors are removed and semantic search returns no results.

Written for commit 2acd40a. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Message cleanup now deletes associated vector embeddings (performed before removing stored messages) so cleared conversations no longer appear in semantic search; cleanup runs across all of a user’s conversations (paginated) and logs vector-delete errors without blocking message removal.
  • Tests

    • Added tests validating vector deletion during conversation clears and user-wide paginated cleanup.
  • Chores

    • Added changelog entry for the patch release.

@changeset-bot
Copy link

changeset-bot bot commented Mar 15, 2026

🦋 Changeset detected

Latest commit: 2acd40a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@voltagent/core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@joggrbot

This comment has been minimized.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ac32e4f7-fe8e-4237-ac9c-983bf125f1de

📥 Commits

Reviewing files that changed from the base of the PR and between 134da78 and 2acd40a.

📒 Files selected for processing (2)
  • packages/core/src/memory/index.ts
  • packages/core/src/memory/semantic-search.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/memory/index.ts

📝 Walkthrough

Walkthrough

Memory.clearMessages now deletes associated vector embeddings (by collecting message vector IDs per conversation or per user with pagination) before clearing message storage when a vector adapter is configured; deletion errors are logged and do not block message clearing.

Changes

Cohort / File(s) Summary
Changelog Entry
.changeset/mean-pets-perform.md
Adds a patch changelog describing the fix: Memory.clearMessages deletes vector embeddings when a vector adapter is configured.
Memory Core Implementation
packages/core/src/memory/index.ts
Introduces VECTOR_CLEAR_CONVERSATION_PAGE_SIZE, adds helper getMessageVectorIdsForClear(userId, conversationId?) to collect vector IDs (msg_<conversationId>_<messageId>), and calls vector.deleteBatch (if configured) before storage.clearMessages; deletion errors are logged and do not prevent clearing.
Semantic Search Tests
packages/core/src/memory/semantic-search.spec.ts
Adds tests validating per-conversation and paginated user-wide vector cleanup, introduces PagedConversationStorageAdapter test helper, and asserts vector.deleteBatch calls and that semantic search returns zero results after clearing.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Caller
  participant Memory as Memory
  participant Storage as MessageStorageAdapter
  participant Vector as VectorAdapter
  participant Logger as Logger

  Caller->>Memory: clearMessages(userId[, conversationId])
  alt conversationId provided
    Memory->>Storage: getMessages(conversationId)
  else no conversationId
    Memory->>Storage: getConversationsByUserId(page...)
    Storage-->>Memory: conversation pages
    Memory->>Storage: getMessages(conversation) (per page)
  end
  Storage-->>Memory: messages
  Memory->>Vector: deleteBatch([msg_<conv>_<msgId>...]) (if vector configured)
  Vector-->>Memory: result / error
  Memory->>Logger: warn on vector deletion errors (non-blocking)
  Memory->>Storage: clearMessages(userId[, conversationId])
  Storage-->>Memory: ack
  Memory-->>Caller: resolved
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇 I nibble IDs by moonlight's beam,

msg_42_7 quietly leaves the stream,
Vectors vanish, searches sweep clean,
Hops of code keep memory neat and lean,
Thump-thump — no ghosts in the machine ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: delete stale vectors when clearing messages' clearly summarizes the main change: deleting vector entries when Memory.clearMessages() is called.
Description check ✅ Passed The description covers all required template sections, explains the bug and fix clearly, links issue #1148, notes tests and changesets added, and includes verification details.
Linked Issues check ✅ Passed The PR fully addresses issue #1148 by implementing vector deletion when clearMessages() is called for both conversation and user-scoped clears, ensuring semantic search no longer returns deleted content.
Out of Scope Changes check ✅ Passed All code changes (vector cleanup logic, pagination helper, and regression tests) are directly related to fixing the vector synchronization issue described in issue #1148.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/memory-clear-vectors-1148
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@omeraplak omeraplak mentioned this pull request Mar 15, 2026
5 tasks
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/core/src/memory/index.ts">

<violation number="1" location="packages/core/src/memory/index.ts:407">
P1: User-wide clears only collect vectors from the first page of conversations, so stale vectors remain once a user has more than the adapter's default page size.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/core/src/memory/index.ts (1)

179-184: Consider using this.logger?.warn for consistent logging.

The class has a logger property and uses console.warn directly here, while other similar warning patterns in the codebase (e.g., line 304 in deleteConversation, line 371 in getMessagesWithSemanticSearch) also use console.warn. However, for observability and configurability, consider using this.logger?.warn with a fallback to console.warn if needed, similar to how logger is used in saveMessageWithContext (lines 1056-1058).

♻️ Optional: Use logger with console fallback
       } catch (error) {
-        console.warn(
+        (this.logger?.warn ?? console.warn)(
           `Failed to delete vectors while clearing messages for user ${userId}${conversationId ? ` conversation ${conversationId}` : ""}:`,
           error,
         );
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/memory/index.ts` around lines 179 - 184, Replace the direct
console.warn call in the catch block that logs deletion failures with the class
logger: use this.logger?.warn(...) and provide a console fallback (e.g.,
console.warn(...)) so logging is consistent with other methods (see
saveMessageWithContext, deleteConversation, getMessagesWithSemanticSearch); keep
the same message format and include the error object when calling
this.logger?.warn to preserve details.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/core/src/memory/index.ts`:
- Around line 179-184: Replace the direct console.warn call in the catch block
that logs deletion failures with the class logger: use this.logger?.warn(...)
and provide a console fallback (e.g., console.warn(...)) so logging is
consistent with other methods (see saveMessageWithContext, deleteConversation,
getMessagesWithSemanticSearch); keep the same message format and include the
error object when calling this.logger?.warn to preserve details.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5991c27a-1e5c-49cd-879e-3104e2d65146

📥 Commits

Reviewing files that changed from the base of the PR and between 19c4fcf and 15f62d1.

📒 Files selected for processing (3)
  • .changeset/mean-pets-perform.md
  • packages/core/src/memory/index.ts
  • packages/core/src/memory/semantic-search.spec.ts

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 15, 2026

Deploying voltagent with  Cloudflare Pages  Cloudflare Pages

Latest commit: 2acd40a
Status: ✅  Deploy successful!
Preview URL: https://1c59f707.voltagent.pages.dev
Branch Preview URL: https://fix-memory-clear-vectors-114.voltagent.pages.dev

View logs

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/core/src/memory/semantic-search.spec.ts">

<violation number="1" location="packages/core/src/memory/semantic-search.spec.ts:41">
P2: This helper overrides the wrong method, so the new test never exercises paginated user-wide cleanup.</violation>
</file>

<file name="packages/core/src/memory/index.ts">

<violation number="1" location="packages/core/src/memory/index.ts:412">
P2: This paginated query needs a deterministic unique sort. As written, offset paging over `queryConversations()` can skip conversations with identical timestamps, leaving some vectors undeleted during user-wide `clearMessages()`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

let offset = 0;

while (true) {
const conversations = await this.storage.queryConversations({
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 15, 2026

Choose a reason for hiding this comment

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

P2: This paginated query needs a deterministic unique sort. As written, offset paging over queryConversations() can skip conversations with identical timestamps, leaving some vectors undeleted during user-wide clearMessages().

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/memory/index.ts, line 412:

<comment>This paginated query needs a deterministic unique sort. As written, offset paging over `queryConversations()` can skip conversations with identical timestamps, leaving some vectors undeleted during user-wide `clearMessages()`.</comment>

<file context>
@@ -404,12 +406,27 @@ export class Memory {
+    let offset = 0;
+
+    while (true) {
+      const conversations = await this.storage.queryConversations({
+        userId,
+        limit: VECTOR_CLEAR_CONVERSATION_PAGE_SIZE,
</file context>
Fix with Cubic

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/core/src/memory/semantic-search.spec.ts (1)

526-572: Make pagination assertion explicit to avoid false positives.

After forcing pagination in the adapter, add assertions on queryConversations call sequence (e.g., offsets 0, 2) so this test proves multi-page traversal instead of only final state.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/memory/semantic-search.spec.ts` around lines 526 - 572, Add
explicit assertions that pagination occurred by spying/mocking the
PagedConversationStorageAdapter.queryConversations calls and asserting it was
invoked for multiple offsets (e.g., 0 then 2) when clearMessages runs; locate
the test that creates the PagedConversationStorageAdapter instance (symbol
PagedConversationStorageAdapter) and, before calling
pagedMemory.clearMessages(userId), attach a spy to
pagedStorage.queryConversations and after clearMessages assert the call sequence
includes queries with offset 0 and offset 2 (or expected page sizes) to prove
multi-page traversal rather than only checking final cleared state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/memory/semantic-search.spec.ts`:
- Around line 36-52: The test helper currently overrides
PagedConversationStorageAdapter.getConversationsByUserId but
Memory.clearMessages uses storage.queryConversations, so the pagination path
isn't exercised; update the helper to override queryConversations (not
getConversationsByUserId) in class PagedConversationStorageAdapter and implement
it to always page results in small chunks (e.g., respect offset but enforce a
fixed page size by using limit = Math.min(options?.limit ?? Infinity,
this.defaultPageSize) or ignore incoming limit in favor of this.defaultPageSize)
so multi-page traversal is triggered; reference the class
PagedConversationStorageAdapter, method queryConversations, and ensure
compatibility with Memory.clearMessages which calls storage.queryConversations.

---

Nitpick comments:
In `@packages/core/src/memory/semantic-search.spec.ts`:
- Around line 526-572: Add explicit assertions that pagination occurred by
spying/mocking the PagedConversationStorageAdapter.queryConversations calls and
asserting it was invoked for multiple offsets (e.g., 0 then 2) when
clearMessages runs; locate the test that creates the
PagedConversationStorageAdapter instance (symbol
PagedConversationStorageAdapter) and, before calling
pagedMemory.clearMessages(userId), attach a spy to
pagedStorage.queryConversations and after clearMessages assert the call sequence
includes queries with offset 0 and offset 2 (or expected page sizes) to prove
multi-page traversal rather than only checking final cleared state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc70dc2e-28ab-4f33-8dc5-74a2e64f486b

📥 Commits

Reviewing files that changed from the base of the PR and between 15f62d1 and 134da78.

📒 Files selected for processing (2)
  • packages/core/src/memory/index.ts
  • packages/core/src/memory/semantic-search.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/memory/index.ts

@omeraplak omeraplak merged commit aa5c4d7 into main Mar 15, 2026
24 checks passed
@omeraplak omeraplak deleted the fix/memory-clear-vectors-1148 branch March 15, 2026 17:29
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.

[BUG] Deleting all messages from memory doesn't delete the agents conversation history.

1 participant