Skip to content

feat(ts-client): support deleting multiple memories#1339

Closed
haosenwang1018 wants to merge 1 commit into
MemMachine:mainfrom
haosenwang1018:feat/ts-client-bulk-delete
Closed

feat(ts-client): support deleting multiple memories#1339
haosenwang1018 wants to merge 1 commit into
MemMachine:mainfrom
haosenwang1018:feat/ts-client-bulk-delete

Conversation

@haosenwang1018
Copy link
Copy Markdown
Contributor

Purpose of the change

Add bulk memory deletion support to the TypeScript client so it matches the existing REST API delete payloads.

Description

Fixes #1249

This change updates MemMachineMemory.delete() in the TypeScript client to accept either a single ID or a list of IDs:

  • memory.delete('1', 'episodic')
  • memory.delete(['1', '2'], 'episodic')

Behavior:

  • single IDs keep using episodic_id / semantic_id
  • multiple IDs use episodic_ids / semantic_ids
  • validation now rejects empty arrays and arrays containing empty IDs

Also added regression coverage in packages/ts-client/tests/memmachine-memory.spec.ts for:

  • deleting multiple episodic memories
  • deleting multiple semantic memories
  • rejecting invalid mixed arrays

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g., code style improvements, linting)
  • Documentation update
  • Project Maintenance (updates to build scripts, CI, etc., that do not affect the main project)
  • Security (improves security without changing functionality)

How Has This Been Tested?

  • Unit Test
  • Integration Test
  • End-to-end Test
  • Test Script (please provide)
  • Manual verification (list step-by-step instructions)

Test command:

  • cd packages/ts-client && npx jest --runInBand tests/memmachine-memory.spec.ts

Checklist

  • I have signed the commit(s) within this pull request
  • My code follows the style guidelines of this project (See STYLE_GUIDE.md)
  • I have performed a self-review of my own code
  • I have commented my code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added unit tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • I have checked my code and corrected any misspellings

Maintainer Checklist

  • Confirmed all checks passed
  • Contributor has signed the commit(s)
  • Reviewed the code
  • Run, Tested, and Verified the change(s) work as expected

@sscargal sscargal requested a review from Copilot April 17, 2026 17:35
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

Note

Copilot was unable to run its full agentic suite in this review.

Adds bulk-delete support to the TypeScript client’s memory deletion API to align with existing REST API payload shapes.

Changes:

  • Updated MemMachineMemory.delete() to accept a single ID or an array of IDs and emit *_id vs *_ids payloads accordingly.
  • Added/updated Jest coverage for multi-delete behavior and invalid ID arrays.
  • Updated validation/error message for invalid IDs.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
packages/ts-client/src/memory/memmachine-memory.ts Extends delete API to accept `string
packages/ts-client/tests/memmachine-memory.spec.ts Adds regression tests for bulk deletion for episodic/semantic and updates validation error expectations.

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

private async _deleteMemory(id: string | string[], memoryType: MemoryType): Promise<void> {
const ids = Array.isArray(id) ? id : [id]

if (ids.length === 0 || ids.some(memoryId => !memoryId || !memoryId.trim())) {
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

Runtime validation can throw a TypeError for non-string values (e.g., JS consumers passing 1), because memoryId.trim() assumes a string. Consider validating typeof memoryId === 'string' (and trimming) so invalid inputs consistently raise MemMachineAPIError instead of crashing with an unexpected exception.

Suggested change
if (ids.length === 0 || ids.some(memoryId => !memoryId || !memoryId.trim())) {
if (ids.length === 0 || ids.some(memoryId => typeof memoryId !== 'string' || !memoryId.trim())) {

Copilot uses AI. Check for mistakes.
const ids = Array.isArray(id) ? id : [id]

if (ids.length === 0 || ids.some(memoryId => !memoryId || !memoryId.trim())) {
throw new MemMachineAPIError('Memory ID must be a non-empty string or non-empty string array')
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

The error text is a bit ambiguous (e.g., it doesn’t explicitly state that every element of the array must be a non-empty string). Consider rewording to something unambiguous like: "Memory ID must be a non-empty string or a non-empty array of non-empty strings".

Suggested change
throw new MemMachineAPIError('Memory ID must be a non-empty string or non-empty string array')
throw new MemMachineAPIError('Memory ID must be a non-empty string or a non-empty array of non-empty strings')

Copilot uses AI. Check for mistakes.
Comment on lines +277 to +278
...(memoryType === 'episodic' ? (ids.length === 1 ? { episodic_id: ids[0] } : { episodic_ids: ids }) : {}),
...(memoryType === 'semantic' ? (ids.length === 1 ? { semantic_id: ids[0] } : { semantic_ids: ids }) : {})
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

These nested ternaries are hard to read and will get harder to extend (e.g., if more memory types are added). Consider constructing the payload key/value with a small helper or a single conditional branch (e.g., compute the key name based on memoryType and ids.length) to reduce duplication and improve readability.

Copilot uses AI. Check for mistakes.
Comment on lines +264 to 266
if (ids.length === 0 || ids.some(memoryId => !memoryId || !memoryId.trim())) {
throw new MemMachineAPIError('Memory ID must be a non-empty string or non-empty string array')
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

The new validation explicitly rejects empty arrays (ids.length === 0), but the added tests only cover empty strings and arrays containing an empty string. Add a unit test asserting memory.delete([], 'episodic') (and/or semantic) rejects with the same error to cover the empty-array branch.

Copilot uses AI. Check for mistakes.
@sscargal
Copy link
Copy Markdown
Contributor

@haosenwang1018 thank you for the pull request submission. Please sign your commits, resolve the unit test failures, and review the CoPilot feedback. You only need to resolve the relevant items. Thanks.

@sscargal
Copy link
Copy Markdown
Contributor

This PR has been obsoleted. main has the string | string[] signature, better normalization (dedup + trim), and equivalent batch tests via #1266

@sscargal sscargal closed this May 13, 2026
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.

[Feat]: [Bug]: Typescript Client library to support deleting a list of memories

3 participants