Skip to content

Add LLM-friendly formatting helpers to clients#1311

Merged
sscargal merged 4 commits intoMemMachine:mainfrom
edwinyyyu:format_memories
Apr 17, 2026
Merged

Add LLM-friendly formatting helpers to clients#1311
sscargal merged 4 commits intoMemMachine:mainfrom
edwinyyyu:format_memories

Conversation

@edwinyyyu
Copy link
Copy Markdown
Contributor

@edwinyyyu edwinyyyu commented Apr 8, 2026

Purpose of the change

Both clients currently have no way of formatting memories in LLM-friendly/context-efficient format.

Description

Based on the logic of server's string_from_episode_context and internal formatting for semantic memories, add functions to do the same thing in clients.

Written entirely by Claude Code.

Fixes/Closes

Addresses client/server form of #1278, but does not solve for MCP, which needs a redesign.

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)

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

@edwinyyyu
Copy link
Copy Markdown
Contributor Author

Changes from Annotated to Field directly are to satisfy the type checker. There is no need to use Annotated.

Signed-off-by: Edwin Yu <edwinyyyu@gmail.com>
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

Adds client-side helpers to render episodic + semantic memory results into a compact, LLM-friendly string/JSON format, mirroring server-side formatting so consumers can trim context usage.

Changes:

  • Added TS + Python formatting helpers for episodic episodes, semantic features, and combined search results.
  • Exported the new helpers from each client’s public API surface.
  • Added unit tests for both clients’ formatting behavior; updated TS list typing surface (new ListMemoriesResult + list() return type).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/ts-client/src/memory/format.ts New TS formatting helpers for episodes/semantic/search results
packages/ts-client/src/memory/index.ts Re-export formatting helpers + new list result type
packages/ts-client/src/memory/memmachine-memory.ts list() now returns ListMemoriesResult
packages/ts-client/src/memory/memmachine-memory.types.ts Introduces ListMemoriesResult type
packages/ts-client/tests/format.spec.ts Jest coverage for TS formatting helpers
packages/client/src/memmachine_client/format.py New Python formatting helpers
packages/client/src/memmachine_client/init.py Exposes formatting helpers in package exports
packages/client/client_tests/test_format.py Pytest coverage for Python formatting helpers
packages/common/src/memmachine_common/api/spec.py Refactors selected API spec model field declarations

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

Comment on lines +166 to +171
export interface ListMemoriesResult {
status: number
content: {
episodic_memory?: EpisodicMemory[]
semantic_memory?: SemanticMemory[]
}
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

ListMemoriesResult.content.episodic_memory is typed as EpisodicMemory[], but /memories/list returns Episode objects (no score, and includes fields like session_key, sequence_num, content_type, etc., per memmachine_common.api.spec.ListResultContent). This makes the TS client types inaccurate and can mislead consumers. Define a dedicated list-episode type (or reuse a generated Episode type) and use it here instead of EpisodicMemory.

Copilot uses AI. Check for mistakes.
Comment thread packages/ts-client/src/memory/memmachine-memory.ts Outdated
Comment thread packages/ts-client/src/memory/memmachine-memory.ts Outdated
Comment thread packages/ts-client/src/memory/format.ts Outdated
Comment on lines +61 to +68
export function formatEpisodes(episodes: EpisodicMemory[]): string {
let result = ''
for (const episode of episodes) {
const date = new Date(episode.created_at)
const dateStr = _formatDate(date)
const timeStr = _formatTime(date)
result += `[${dateStr} at ${timeStr}] ${episode.producer_id}: ${JSON.stringify(episode.content)}\n`
}
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

formatEpisodes only accepts EpisodicMemory[], but list responses return a different episode shape (and even search responses may have optional/nullable score). Since this formatter only needs created_at, producer_id, and content, consider changing the parameter type to a minimal structural type (or a union of search/list episode types) so it can be used safely with both search() and list() results.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +116
export function formatSearchResult(result: SearchMemoriesResult): string {
const sections: string[] = []

if (result.content.episodic_memory) {
const episodes = [
...result.content.episodic_memory.long_term_memory.episodes,
...result.content.episodic_memory.short_term_memory.episodes
]
if (episodes.length > 0) {
sections.push(`[Episodic Memory]\n${formatEpisodes(episodes)}`)
}
}

if (result.content.semantic_memory && result.content.semantic_memory.length > 0) {
sections.push(`[Semantic Memory]\n${formatSemanticMemories(result.content.semantic_memory)}`)
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

formatSearchResult defensively treats episodic_memory/semantic_memory as optional, but the exported TS type SearchMemoriesResult currently requires both to be present. The server spec allows these fields to be null/omitted (e.g., when searching only one memory type, and FastAPI uses response_model_exclude_none). Updating the TS SearchMemoriesResult definition to reflect nullable/optional fields will make this helper and the client’s runtime behavior consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +139 to +143
describe('formatSearchResult', () => {
it('returns empty string for empty result', () => {
const result: SearchMemoriesResult = {
status: 0,
content: {
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

formatSearchResult has branches for missing/null episodic_memory and semantic_memory, but the test suite doesn’t cover those cases. Add a test where semantic_memory is null/undefined and/or episodic_memory is null to ensure this behavior stays correct (server responses can omit these fields when searching a single type).

Copilot uses AI. Check for mistakes.
edwinyyyu and others added 3 commits April 15, 2026 14:42
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Edwin Yu <92917168+edwinyyyu@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Edwin Yu <92917168+edwinyyyu@users.noreply.github.com>
Signed-off-by: Edwin Yu <edwinyyyu@gmail.com>
@sscargal sscargal merged commit 88a71eb into MemMachine:main Apr 17, 2026
45 checks passed
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.

3 participants