feat(api): add POST /agentmemory/reindex-vectors to re-embed after a model swap#956
feat(api): add POST /agentmemory/reindex-vectors to re-embed after a model swap#956shgew wants to merge 2 commits into
Conversation
…model swap
Switching the embedding model or dimensions invalidates the persisted
vectors. Today the only paths are full-restart rebuild or
AGENTMEMORY_DROP_STALE_INDEX, neither of which re-embeds history on
demand without a restart.
This adds a new REST endpoint (and the backing mem::reindex-vectors
iii function) that re-embeds every observation and memory in place.
The live index keeps serving during the rebuild; the fresh index is
built off to the side, validated (failed === 0), then atomically
swapped in via IndexPersistence.restoreFrom and persisted
synchronously.
Builds on the existing migrateVectorIndex helper, which already
constructed a fresh index but discarded it. The new reindexVectors()
keeps the fresh index and atomically swaps it.
Tests:
- test/reindex-vectors.test.ts (full coverage of the new function +
REST handler).
- test/vector-index-dimensions.test.ts extended.
REST endpoint count bumps 128 -> 129. No MCP tool added.
Signed-off-by: Hleb Shauchenka <me@marleb.org>
|
@shgew is attempting to deploy a commit to the rohitg00's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a Changesreindex-vectors feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/functions/search.ts`:
- Around line 375-380: The code performs a state-changing operation when
swapping the vector index (within the if block where stats.success is true and
swapped is set to true) but fails to record an audit entry as required by coding
guidelines. After the swapped variable is set to true and flushIndexSave() is
awaited, add a call to recordAudit() to log this state-changing operation,
including relevant details such as the operation type (index swap) and any
pertinent context like the endpoint name (ep.name) and dimensions
(ep.dimensions) to maintain a complete audit trail.
- Around line 375-378: The code mutates live state via vi.restoreFrom(index) on
line 376 before persisting the change via flushIndexSave() on line 377. If the
persistence call throws an error, the swap has already happened in live state
but callers perceive a failure and may retry the operation unnecessarily.
Reorder these operations so that flushIndexSave() is called before
vi.restoreFrom(index), or alternatively wrap the flushIndexSave() call in a
try-catch block and return a structured partial-failure response (indicating the
swap succeeded but persistence failed) when an error is caught after the state
mutation has already occurred. This ensures callers can distinguish between a
swap that never happened versus a swap that succeeded but failed to persist.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6f97e1f2-986c-4978-9fc6-ef67ac95770b
📒 Files selected for processing (7)
README.mdsrc/functions/migrate-vector-index.tssrc/functions/search.tssrc/index.tssrc/triggers/api.tstest/reindex-vectors.test.tstest/vector-index-dimensions.test.ts
The previous flow mutated the live vector index via vi.restoreFrom() and then awaited flushIndexSave() with no guard. If the persistence call threw, callers saw the failure but the in-memory swap had already happened, so retries would have operated on a half-applied state. Move flushIndexSave() into a try/catch after the live swap. On failure, return a structured response with success:false, swapped:true, and the error message so operators can distinguish 'swap never happened' from 'swap applied but persistence failed'. Also record a vector_index_swap audit entry on the successful path, per the project rule that state-changing operations carry an audit trail.
What
Add a new REST endpoint
POST /agentmemory/reindex-vectorsand the backingmem::reindex-vectorsiii function. Re-embeds every observation and memory in place. The live index keeps serving during the rebuild; the fresh index is built off to the side, validated (failed === 0), then atomically swapped in viaIndexPersistence.restoreFromand persisted synchronously.Why
Switching the embedding model or dimensions invalidates the persisted vectors. Today the only paths are full-restart rebuild or
AGENTMEMORY_DROP_STALE_INDEX, neither of which re-embeds history on demand without a restart.How
Builds on the existing
migrateVectorIndexhelper, which already constructed a fresh index but discarded it. The newreindexVectors()keeps the fresh index and atomically swaps it.Tests
test/reindex-vectors.test.ts(new file, 9 cases) - full coverage of the new function + REST handler.test/vector-index-dimensions.test.tsextended.Compatibility
Additive endpoint. No existing endpoint changed. REST endpoint count bumps 128 → 129.
How to verify
Summary by CodeRabbit