Skip to content

Conversation

@DanielSLew
Copy link
Contributor

@DanielSLew DanielSLew commented Dec 31, 2025

Adds thread cloning to create independent copies of conversations that can diverge.

image
// Clone a thread
const { thread, clonedMessages } = await memory.cloneThread({
  sourceThreadId: 'thread-123',
  title: 'My Clone',
  options: {
    messageLimit: 10, // optional: only copy last N messages
  },
});

// Check if a thread is a clone
if (memory.isClone(thread)) {
  const source = await memory.getSourceThread(thread.id);
}

// List all clones of a thread
const clones = await memory.listClones('thread-123');

Includes:

  • Storage implementations for InMemory, PostgreSQL, LibSQL, Upstash
  • API endpoint: POST /api/memory/threads/:threadId/clone
  • Embeddings created for cloned messages (semantic recall)
  • Clone button in playground UI Memory tab
  • Unit and integration tests

Note

Adds end-to-end support for cloning conversation threads, enabling independent branches of a conversation.

  • Core: Memory.cloneThread() plus utilities (isClone, getCloneMetadata, getSourceThread, listClones, getCloneHistory); embeddings generated for cloned messages when semantic recall is enabled
  • Storage: implementations for InMemory, PostgreSQL, LibSQL, and Upstash; new types (StorageCloneThreadInput/Output, ThreadCloneMetadata)
  • Server: new endpoint POST /api/memory/threads/:threadId/clone with schemas and route wiring
  • Client SDK: thread.clone(params) and related types (CloneMemoryThreadParams/Response)
  • UI: Clone button in playground Memory tab with navigation to the new thread
  • Docs: references for client SDK, cloneThread, clone utilities, and server routes
  • Tests: unit and integration coverage for cloning behavior, filters, limits, metadata, and embeddings

Written by Cursor Bugbot for commit e11022a. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • Clone memory threads into independent copies with optional message filtering/limits, custom IDs/titles, and embeddings for cloned messages
    • Clone utilities: detect clones, retrieve source thread, list clones, and view clone history
    • API endpoint and a "Clone Thread" button in the playground Memory tab
  • Tests

    • Extensive integration and unit tests covering cloning scenarios, filters, limits, metadata, and embeddings
  • Documentation

    • Added changelog and docs for cloneThread and clone utilities

✏️ Tip: You can customize this high-level summary in your review settings.

DanielSLew and others added 8 commits December 23, 2025 16:03
Adds the ability to clone conversation threads with all their messages. This creates an independent copy that can diverge from the original.

Features:
- `cloneThread()` method on Memory class with message filtering options
- Clone metadata stored on new thread (sourceThreadId, clonedAt, lastMessageId)
- Utility methods: isClone(), getCloneMetadata(), getSourceThread(), listClones(), getCloneHistory()
- Embeddings created for cloned messages when semantic recall is enabled
- API endpoint: POST /api/memory/threads/:threadId/clone
- Clone button in playground UI Memory tab

Implemented for all storage adapters: InMemory, PostgreSQL, LibSQL, Upstash

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@changeset-bot
Copy link

changeset-bot bot commented Dec 31, 2025

🦋 Changeset detected

Latest commit: e11022a

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

This PR includes changesets to release 22 packages
Name Type
@mastra/playground-ui Patch
@mastra/client-js Patch
@mastra/memory Patch
@mastra/server Patch
@mastra/upstash Patch
@mastra/core Patch
@mastra/libsql Patch
@mastra/pg Patch
@mastra/react Patch
@mastra/agent-builder Patch
@mastra/express Patch
@mastra/hono Patch
@mastra/dane Patch
@mastra/longmemeval Patch
@mastra/deployer Patch
@mastra/mcp-docs-server Patch
mastra Patch
@mastra/deployer-cloud Patch
@mastra/deployer-cloudflare Patch
@mastra/deployer-netlify Patch
@mastra/deployer-vercel Patch
create-mastra 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

@vercel
Copy link

vercel bot commented Dec 31, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
assistant-ui Ready Ready Preview, Comment Dec 31, 2025 7:51pm
mastra-docs Ready Ready Preview, Comment Dec 31, 2025 7:51pm
mastra-docs-1.x Ready Ready Preview, Comment Dec 31, 2025 7:51pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 31, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds thread-cloning across the memory subsystem: new storage types and cloneThread implementations (InMemory, PG, LibSQL, Upstash), core Memory APIs and utilities, server route and schemas, client SDK method and types, Playground UI hook/button, documentation, and extensive unit/integration tests (including a duplicated suite).

Changes

Cohort / File(s) Summary
Changelog
\.changeset/spotty-grapes-fetch.md
Adds changelog entry describing thread cloning feature and usage notes.
Client SDK
client-sdks/client-js/src/types.ts, client-sdks/client-js/src/resources/memory-thread.ts
Adds CloneMemoryThreadParams / CloneMemoryThreadResponse types and MemoryThread.clone() method calling /api/memory/threads/{threadId}/clone.
Core Memory API & Mock
packages/core/src/memory/memory.ts, packages/core/src/memory/mock.ts
Adds abstract cloneThread to MastraMemory and implements delegation in MockMemory.
Core Storage Types & Base
packages/core/src/storage/types.ts, packages/core/src/storage/domains/memory/base.ts
Adds ThreadCloneMetadata, StorageCloneThreadInput, StorageCloneThreadOutput types and base cloneThread (default not-implemented).
In-Memory Storage
packages/core/src/storage/domains/memory/inmemory.ts
Implements cloneThread with ID generation/validation, filtering/limits, metadata and message cloning.
DB Adapters
stores/pg/.../memory/index.ts, stores/libsql/.../memory/index.ts, stores/upstash/.../memory/index.ts
Adds cloneThread implementations in PG, LibSQL, and Upstash with transactions, filters/limits, metadata, and error handling.
Memory Implementation & Utilities
packages/memory/src/index.ts, packages/memory/src/index.test.ts
Adds cloneThread, embedClonedMessages, clone utilities (isClone, getCloneMetadata, getSourceThread, listClones, getCloneHistory), exports clone types, and extensive tests for cloning scenarios.
Server: Schemas, Handler & Route
packages/server/src/server/schemas/memory.ts, packages/server/src/server/handlers/memory.ts, packages/server/src/server/server-adapter/routes/memory.ts
Adds Zod body/response schemas, CLONE_THREAD_ROUTE POST /api/memory/threads/:threadId/clone handler and registers route; handler calls memory.cloneThread.
Playground UI
packages/playground-ui/src/domains/memory/hooks/use-memory.ts, packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
Adds useCloneThread hook and a "Clone Thread" button/flow that triggers cloning and navigates to the cloned thread.
Docs
docs/src/content/en/reference/client-js/memory.mdx, docs/src/content/en/reference/memory/clone-utilities.mdx, docs/src/content/en/reference/memory/cloneThread.mdx, docs/src/content/en/reference/memory/memory-class.mdx, docs/src/content/en/reference/server/routes.mdx
Adds documentation for cloneThread and clone utilities; updates memory-class references and server routes docs.
Tests / Integration
packages/memory/integration-tests/src/shared/agent-memory.ts
Adds extensive integration tests for thread cloning (note: contains a duplicated test suite block).

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • abhiaiyer91
  • NikAiyer
  • kmk142789

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main feature added: thread cloning functionality in the memory subsystem, which is the central change across all affected files.

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.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 31, 2025

🚨 Redirect Validation Failed

The redirect validation found issues in vercel.json (duplicate sources or broken destination links).

Action Required: Review and fix the redirect configuration.

📋 View workflow logs for details

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 (6)
packages/memory/src/index.test.ts (1)

144-472: cloneThread tests thoroughly cover behavior and edge cases

The cloneThread suite exercises default cloning, custom titles, limits, date/ID filters, cross‑resource clones, metadata overrides, and error paths (sourceThreadId missing, duplicate newThreadId), which aligns well with the storage‑level semantics.

One small future‑proofing tweak would be to avoid depending on clonedMessages[0]/[1] ordering in the message‑limit and filter tests by asserting on sorted createdAt or sets of texts, in case a backend ever changes its default ordering.

packages/core/src/memory/memory.ts (1)

747-752: Abstract cloneThread API is well‑shaped; consider updating the docstring

The new abstract cloneThread(args: StorageCloneThreadInput): Promise<StorageCloneThreadOutput> cleanly exposes the storage‑level clone contract and matches the shared types.

Since StorageCloneThreadInput supports messageLimit and messageFilter, you might want to tweak the comment from “Clones a thread with all its messages” to “Clones a thread (optionally with a filtered subset of messages)” for accuracy.

packages/memory/integration-tests/src/shared/agent-memory.ts (1)

1287-1686: Thread cloning integration tests look solid; consider hardening timing around embeddings

This Thread Cloning block gives strong end‑to‑end coverage (agent + storage + vector + semantic recall), including custom IDs, history, and searchability of cloned embeddings.

The two setTimeout(500) waits around embedding in the last test could be a source of flakiness under slow I/O. As a later improvement, consider polling recall until results appear (with a max retry) or wiring in an explicit sync point from the vector adapter instead of fixed sleeps.

packages/server/src/server/handlers/memory.ts (1)

41-42: CLONE_THREAD_ROUTE correctly wires the HTTP API to memory.cloneThread

The new route:

  • Validates threadId via validateBody and path schema.
  • Resolves the correct MastraMemory via agentId.
  • Delegates to memory.cloneThread with { sourceThreadId: threadId!, newThreadId, resourceId, title, metadata, options }.
  • Uses dedicated body/response schemas and funnels failures through handleError('Error cloning thread').

The only minor nit is the description “Creates a copy … with all its messages” while the options allow cloning a subset; you might later clarify that in the summary.

Also applies to: 496-530

packages/core/src/storage/types.ts (1)

141-191: Clone typing is clear; watch clonedAt representation across persisted stores

ThreadCloneMetadata, StorageCloneThreadInput, and StorageCloneThreadOutput nicely document the clone contract and are used consistently across memory backends and APIs.

One subtle type/detail mismatch to be aware of: in PG (and likely other SQL stores), metadata is JSON‑stringified on write and JSON.parsed on read, so cloneMetadata.clonedAt will come back as a string unless you normalize it in getCloneMetadata. Right now the type advertises Date, and tests only assert instanceof Date on the in‑memory backend.

As a follow‑up, consider either:

  • Normalizing clonedAt to a Date in getCloneMetadata, or
  • Relaxing the type to Date | string and documenting that it may need coercion when coming from a DB‑backed store.
packages/memory/src/index.ts (1)

1286-1309: Consider potential performance impact for resources with many threads.

This method fetches all threads for a resource (perPage: false) and filters in memory. For resources with a large number of threads, this could be slow. The current approach is acceptable for the initial implementation, but consider adding storage-level filtering (querying by metadata.clone.sourceThreadId) if this becomes a performance bottleneck.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 178c2f4 and 1ceb1b7.

📒 Files selected for processing (19)
  • .changeset/spotty-grapes-fetch.md
  • client-sdks/client-js/src/resources/memory-thread.ts
  • client-sdks/client-js/src/types.ts
  • packages/core/src/memory/memory.ts
  • packages/core/src/memory/mock.ts
  • packages/core/src/storage/domains/memory/base.ts
  • packages/core/src/storage/domains/memory/inmemory.ts
  • packages/core/src/storage/types.ts
  • packages/memory/integration-tests/src/shared/agent-memory.ts
  • packages/memory/src/index.test.ts
  • packages/memory/src/index.ts
  • packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
  • packages/playground-ui/src/domains/memory/hooks/use-memory.ts
  • packages/server/src/server/handlers/memory.ts
  • packages/server/src/server/schemas/memory.ts
  • packages/server/src/server/server-adapter/routes/memory.ts
  • stores/libsql/src/storage/domains/memory/index.ts
  • stores/pg/src/storage/domains/memory/index.ts
  • stores/upstash/src/storage/domains/memory/index.ts
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Run pnpm typecheck to validate TypeScript types across all packages

Files:

  • packages/server/src/server/server-adapter/routes/memory.ts
  • packages/playground-ui/src/domains/memory/hooks/use-memory.ts
  • packages/core/src/memory/memory.ts
  • packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
  • packages/core/src/memory/mock.ts
  • packages/memory/integration-tests/src/shared/agent-memory.ts
  • packages/core/src/storage/types.ts
  • packages/server/src/server/schemas/memory.ts
  • stores/pg/src/storage/domains/memory/index.ts
  • client-sdks/client-js/src/resources/memory-thread.ts
  • packages/server/src/server/handlers/memory.ts
  • client-sdks/client-js/src/types.ts
  • stores/libsql/src/storage/domains/memory/index.ts
  • packages/memory/src/index.test.ts
  • packages/core/src/storage/domains/memory/inmemory.ts
  • packages/memory/src/index.ts
  • packages/core/src/storage/domains/memory/base.ts
  • stores/upstash/src/storage/domains/memory/index.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Run pnpm prettier:format to format code and pnpm format to run linting with auto-fix across all packages

Files:

  • packages/server/src/server/server-adapter/routes/memory.ts
  • packages/playground-ui/src/domains/memory/hooks/use-memory.ts
  • packages/core/src/memory/memory.ts
  • packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
  • packages/core/src/memory/mock.ts
  • packages/memory/integration-tests/src/shared/agent-memory.ts
  • packages/core/src/storage/types.ts
  • packages/server/src/server/schemas/memory.ts
  • stores/pg/src/storage/domains/memory/index.ts
  • client-sdks/client-js/src/resources/memory-thread.ts
  • packages/server/src/server/handlers/memory.ts
  • client-sdks/client-js/src/types.ts
  • stores/libsql/src/storage/domains/memory/index.ts
  • packages/memory/src/index.test.ts
  • packages/core/src/storage/domains/memory/inmemory.ts
  • packages/memory/src/index.ts
  • packages/core/src/storage/domains/memory/base.ts
  • stores/upstash/src/storage/domains/memory/index.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/**/*.{ts,tsx}: All packages must use TypeScript with strict type checking enabled
Use telemetry decorators for observability across components

Files:

  • packages/server/src/server/server-adapter/routes/memory.ts
  • packages/playground-ui/src/domains/memory/hooks/use-memory.ts
  • packages/core/src/memory/memory.ts
  • packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
  • packages/core/src/memory/mock.ts
  • packages/memory/integration-tests/src/shared/agent-memory.ts
  • packages/core/src/storage/types.ts
  • packages/server/src/server/schemas/memory.ts
  • packages/server/src/server/handlers/memory.ts
  • packages/memory/src/index.test.ts
  • packages/core/src/storage/domains/memory/inmemory.ts
  • packages/memory/src/index.ts
  • packages/core/src/storage/domains/memory/base.ts
.changeset/*.md

⚙️ CodeRabbit configuration file

.changeset/*.md: Changeset files are really important for keeping track of changes in the project. They'll be used to generate release notes and inform users about updates.

Review the changeset file according to these guidelines:

  • The target audience are developers
  • Write short, direct sentences that anyone can understand. Avoid commit messages, technical jargon, and acronyms. Use action-oriented verbs (Added, Fixed, Improved, Deprecated, Removed)
  • Avoid generic phrases like "Update code", "Miscellaneous improvements", or "Bug fixes"
  • Highlight outcomes! What does change for the end user? Do not focus on internal implementation details
  • Add context like links to issues or PRs when relevant
  • If the change is a breaking change or is adding a new feature, ensure that a code example is provided. This code example should show the public API usage (the before and after). Do not show code examples of internal implementation details.
  • Keep the formatting easy-to-read and scannable. If necessary, use bullet points or multiple paragraphs (Use bold text as the heading for these sections, do not use markdown headings).
  • For larger, more substantial changes, also answer the "Why" behind the changes
  • Each changeset file contains a YAML frontmatter at the top. It will be one or more package names followed by a colon and the type of change (patch, minor, major). Do not modify this frontmatter. Check that the description inside the changeset file only applies to the packages listed in the frontmatter. Do not allow descriptions that mention changes to packages not listed in the frontmatter. In these cases, the user must create a separate changeset file for those packages.

Files:

  • .changeset/spotty-grapes-fetch.md
packages/playground-ui/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/playground-ui/CLAUDE.md)

packages/playground-ui/src/**/*.{ts,tsx}: Use Tailwind CSS (v3.x) for all styling in packages/playground-ui components
Use design tokens from src/ds/tokens/index.ts instead of arbitrary Tailwind values (e.g., do not use bg-[#1A1A1A])
Use PascalCase for component names (e.g., EntryList)
Use kebab-case for component filenames (e.g., entry-list.tsx)
Use named exports only; avoid default exports in components
Use TanStack Query for all data fetching hooks in packages/playground-ui
Use useMastraClient SDK for API calls instead of direct fetch() calls
Export explicit prop types separately from components (e.g., export type ComponentProps = {...})
Prefer derived values over useState + useEffect; calculate values directly when possible
Keep type definitions alongside components within the same file
Minimize useEffect usage in components; only use it when necessary

packages/playground-ui/src/**/*.{ts,tsx}: Use Tailwind CSS v3.x for all styling in packages/playground-ui
Use design tokens from src/ds/tokens/index.ts for Tailwind styling in packages/playground-ui; forbidden to use arbitrary values (e.g., bg-[#1A1A1A]) unless explicitly requested
Use PascalCase for component names in packages/playground-ui
Use kebab-case for component file names in packages/playground-ui
Use named exports only; avoid default exports in packages/playground-ui
Use TanStack Query for all data-fetching hooks in packages/playground-ui; forbidden to use direct fetch() calls
Use useMastraClient SDK for API calls in data-fetching hooks in packages/playground-ui
Export explicit prop types separately from components in packages/playground-ui; keep type definitions alongside components
Prefer derived values over useState + useEffect in packages/playground-ui; minimize useEffect usage and calculate values directly when possible
Use TanStack Query for all server state management in packages/playground-ui

Files:

  • packages/playground-ui/src/domains/memory/hooks/use-memory.ts
  • packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
packages/playground-ui/src/**/*.{tsx,css,scss}

📄 CodeRabbit inference engine (packages/playground-ui/CLAUDE.md)

Prefer Tailwind utilities over custom CSS files for shadows, gradients, and other styles

Files:

  • packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
packages/playground-ui/src/**/*.{tsx,css}

📄 CodeRabbit inference engine (packages/playground-ui/.cursor/rules/frontend.mdc)

Prefer Tailwind utilities over custom CSS files for shadows, gradients, and other styling; only use CSS files when Tailwind cannot express the style

Files:

  • packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx
**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{test,spec}.{ts,tsx}: Use Vitest for testing framework in test files
Co-locate test files with source code using naming patterns like *.test.ts or *.spec.ts

Files:

  • packages/memory/src/index.test.ts
🧠 Learnings (4)
📚 Learning: 2025-11-24T16:41:10.784Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/playground-ui/.cursor/rules/frontend.mdc:0-0
Timestamp: 2025-11-24T16:41:10.784Z
Learning: Applies to packages/playground-ui/src/**/*.{ts,tsx} : Use `useMastraClient` SDK for API calls in data-fetching hooks in `packages/playground-ui`

Applied to files:

  • packages/playground-ui/src/domains/memory/hooks/use-memory.ts
📚 Learning: 2025-11-24T16:42:04.244Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/codemod/AGENTS.md:0-0
Timestamp: 2025-11-24T16:42:04.244Z
Learning: Applies to packages/codemod/src/test/__fixtures__/**/*.ts : Create test fixtures by copying examples DIRECTLY from migration guides in `docs/src/content/en/guides/migrations/upgrade-to-v1/` without hallucinating or inventing changes

Applied to files:

  • packages/core/src/memory/mock.ts
  • packages/memory/integration-tests/src/shared/agent-memory.ts
  • packages/memory/src/index.test.ts
📚 Learning: 2025-11-24T16:42:04.244Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/codemod/AGENTS.md:0-0
Timestamp: 2025-11-24T16:42:04.244Z
Learning: Applies to packages/codemod/src/test/__fixtures__/**/*.ts : In output fixtures, ensure all NEGATIVE test cases remain EXACTLY IDENTICAL to their input fixture counterparts to verify the codemod only transforms intended patterns

Applied to files:

  • packages/memory/integration-tests/src/shared/agent-memory.ts
  • packages/memory/src/index.test.ts
📚 Learning: 2025-11-24T16:42:04.244Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/codemod/AGENTS.md:0-0
Timestamp: 2025-11-24T16:42:04.244Z
Learning: Applies to packages/codemod/src/test/**/*.test.ts : Include test cases for multiple occurrences of the transformation pattern, aliased imports, type imports, and mixed imports to verify the codemod works consistently

Applied to files:

  • packages/memory/integration-tests/src/shared/agent-memory.ts
  • packages/memory/src/index.test.ts
🧬 Code graph analysis (15)
packages/server/src/server/server-adapter/routes/memory.ts (1)
packages/server/src/server/handlers/memory.ts (1)
  • CLONE_THREAD_ROUTE (496-530)
packages/playground-ui/src/domains/memory/hooks/use-memory.ts (2)
packages/core/src/agent/agent.ts (1)
  • thread (2788-2959)
packages/playground-ui/src/lib/toast.tsx (1)
  • toast (51-60)
packages/core/src/memory/memory.ts (1)
packages/core/src/storage/types.ts (2)
  • StorageCloneThreadInput (156-181)
  • StorageCloneThreadOutput (186-191)
packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx (2)
packages/core/src/storage/domains/memory/inmemory.ts (1)
  • cloneThread (549-663)
packages/playground-ui/src/domains/memory/hooks/use-memory.ts (1)
  • useCloneThread (105-126)
packages/core/src/memory/mock.ts (2)
packages/core/src/storage/types.ts (2)
  • StorageCloneThreadInput (156-181)
  • StorageCloneThreadOutput (186-191)
packages/memory/src/index.ts (2)
  • StorageCloneThreadInput (1347-1347)
  • StorageCloneThreadOutput (1347-1347)
packages/memory/integration-tests/src/shared/agent-memory.ts (1)
packages/memory/src/index.ts (1)
  • Memory (55-1341)
stores/pg/src/storage/domains/memory/index.ts (5)
packages/core/src/storage/types.ts (3)
  • StorageCloneThreadInput (156-181)
  • StorageCloneThreadOutput (186-191)
  • ThreadCloneMetadata (144-151)
packages/core/src/error/index.ts (1)
  • MastraError (142-142)
packages/core/src/storage/utils.ts (1)
  • createStorageErrorId (208-210)
packages/core/src/memory/types.ts (2)
  • StorageThreadType (36-43)
  • MastraDBMessage (5-5)
packages/core/src/agent/types.ts (1)
  • MastraDBMessage (42-42)
client-sdks/client-js/src/resources/memory-thread.ts (2)
client-sdks/client-js/src/types.ts (2)
  • CloneMemoryThreadParams (309-323)
  • CloneMemoryThreadResponse (325-328)
client-sdks/client-js/src/utils/index.ts (1)
  • requestContextQueryString (110-120)
packages/server/src/server/handlers/memory.ts (2)
packages/server/src/server/schemas/memory.ts (4)
  • threadIdPathParams (5-7)
  • agentIdQuerySchema (12-14)
  • cloneThreadBodySchema (374-391)
  • cloneThreadResponseSchema (396-399)
packages/server/src/server/handlers/utils.ts (1)
  • validateBody (4-15)
client-sdks/client-js/src/types.ts (2)
packages/core/src/memory/types.ts (1)
  • StorageThreadType (36-43)
packages/core/src/agent/types.ts (1)
  • MastraDBMessage (42-42)
stores/libsql/src/storage/domains/memory/index.ts (2)
packages/core/src/storage/types.ts (3)
  • StorageCloneThreadInput (156-181)
  • StorageCloneThreadOutput (186-191)
  • ThreadCloneMetadata (144-151)
packages/core/src/error/index.ts (1)
  • MastraError (142-142)
packages/memory/src/index.test.ts (2)
packages/memory/src/index.ts (1)
  • Memory (55-1341)
packages/core/src/storage/mock.ts (1)
  • InMemoryStore (28-64)
packages/core/src/storage/domains/memory/inmemory.ts (3)
packages/core/src/storage/types.ts (4)
  • StorageCloneThreadInput (156-181)
  • StorageCloneThreadOutput (186-191)
  • StorageMessageType (201-209)
  • ThreadCloneMetadata (144-151)
packages/core/src/memory/types.ts (1)
  • StorageThreadType (36-43)
packages/core/src/storage/utils.ts (1)
  • safelyParseJSON (32-46)
packages/core/src/storage/domains/memory/base.ts (1)
packages/core/src/storage/types.ts (2)
  • StorageCloneThreadInput (156-181)
  • StorageCloneThreadOutput (186-191)
stores/upstash/src/storage/domains/memory/index.ts (4)
packages/core/src/storage/types.ts (3)
  • StorageCloneThreadInput (156-181)
  • StorageCloneThreadOutput (186-191)
  • ThreadCloneMetadata (144-151)
packages/core/src/storage/utils.ts (2)
  • createStorageErrorId (208-210)
  • filterByDateRange (298-320)
packages/core/src/workflows/workflow.ts (1)
  • options (1028-1030)
packages/core/src/memory/types.ts (1)
  • StorageThreadType (36-43)
🪛 GitHub Check: Lint
packages/memory/src/index.test.ts

[failure] 2-2:
'StorageThreadType' is defined but never used. Allowed unused vars must match /^_/u

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Prebuild
  • GitHub Check: test
  • GitHub Check: test (hono)
  • GitHub Check: test
  • GitHub Check: test (express)
  • GitHub Check: test
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (20)
packages/core/src/storage/domains/memory/base.ts (1)

65-77: LGTM!

The abstract cloneThread method follows the established pattern for storage adapters with clear documentation and an informative not-implemented error message.

packages/server/src/server/server-adapter/routes/memory.ts (1)

12-12: LGTM!

The CLONE_THREAD_ROUTE is correctly imported and registered following the established pattern for memory routes.

Also applies to: 39-39

packages/playground-ui/src/domains/agents/components/agent-information/agent-memory.tsx (2)

36-48: LGTM!

The clone thread handler properly awaits the mutation, checks the result before navigation, and relies on the mutation's error handling. The implementation is clean and follows React best practices.


76-90: LGTM!

The Clone Thread UI section is well-implemented with:

  • Clear labels and description for user understanding
  • Appropriate loading state ("Cloning..." vs "Clone")
  • Disabled button during operation to prevent duplicate requests
  • Semantically appropriate Copy icon
.changeset/spotty-grapes-fetch.md (2)

1-38: Changeset follows guidelines well.

The changeset is well-written with:

  • Clear, action-oriented language ("Adds thread cloning...")
  • Practical code example showing public API usage
  • Outcome-focused description (independent copies that can diverge)
  • Appropriate bullet points for implementation details

As per coding guidelines, the content is developer-friendly and scannable.


14-31: All documented APIs are properly implemented—no action needed.

Verification confirms that isClone(), getSourceThread(), and listClones() are all implemented as public methods in packages/memory/src/index.ts (lines 1244, 1262, and 1286 respectively). All three methods have proper documentation and comprehensive test coverage. The code examples in the changeset accurately reflect the actual API implementation.

packages/core/src/memory/mock.ts (1)

309-312: LGTM!

The cloneThread implementation correctly delegates to the underlying memory storage, following the same pattern as other methods in MockMemory.

client-sdks/client-js/src/resources/memory-thread.ts (1)

114-128: LGTM!

The clone method is well-implemented with:

  • Clear JSDoc documentation
  • Correct type usage for parameters and response
  • Consistent pattern matching other methods in the class (e.g., update, delete)
  • Proper handling of requestContext via query string
packages/server/src/server/schemas/memory.ts (1)

371-399: LGTM!

The clone thread schemas are well-structured:

  • cloneThreadBodySchema properly defines all optional parameters with correct types
  • Date coercion (z.coerce.date()) ensures proper parsing from query strings
  • cloneThreadResponseSchema correctly uses existing threadSchema and messageSchema
  • JSDoc comments clearly document the endpoint path and purpose

The schemas align with the corresponding TypeScript types (StorageCloneThreadInput, StorageCloneThreadOutput) used throughout the codebase.

packages/playground-ui/src/domains/memory/hooks/use-memory.ts (1)

105-126: Query key pattern is consistent—no changes needed.

The duplication of agentId in the query key ['memory', 'threads', agentId, agentId] is intentional and correct. In the playground context, resourceId is always set to agentId (as seen in agent-memory.tsx line 32), so the query key created by useThreads is ['memory', 'threads', agentId, agentId]. The mutation hooks correctly invalidate this same key.

packages/memory/src/index.test.ts (1)

474-702: clone utility tests give good coverage of metadata and lineage helpers

The clone utility methods suite validates isClone, getCloneMetadata, getSourceThread, listClones, and getCloneHistory across positive, negative, and non‑existent thread cases, which is exactly what these helpers need. This should catch regressions in clone metadata shape or traversal logic early.

packages/core/src/storage/domains/memory/inmemory.ts (1)

549-663: InMemory cloneThread correctly implements the clone semantics

The in‑memory implementation matches StorageCloneThreadInput/Output semantics:

  • Validates source existence and prevents newThreadId collisions.
  • Applies messageFilter (IDs + date range) first, then messageLimit from the most recent messages via slice(-limit).
  • Builds ThreadCloneMetadata with sourceThreadId, clonedAt, and lastMessageId after filtering/limiting.
  • Creates a new thread with appropriate resourceId, default title (Clone of …), and metadata merged with clone.
  • Clones messages with new IDs while preserving createdAt, role, and content, and returns parsed MastraDBMessages.

This aligns with the tests and PG implementation, and I don’t see correctness issues here.

client-sdks/client-js/src/types.ts (1)

309-328: CloneMemoryThread types align with core and server contracts

CloneMemoryThreadParams mirrors the server’s cloneThreadBodySchema (newThreadId/resourceId/title/metadata/options) plus requestContext, and CloneMemoryThreadResponse matches StorageCloneThreadOutput. Given the threadId comes from the URL in the client resource, this shape looks appropriate.

stores/pg/src/storage/domains/memory/index.ts (1)

16-25: MemoryPG cloneThread is transactional and mirrors in‑memory behavior

The PG implementation:

  • Validates that the source thread exists and that the target newThreadId (or generated UUID) does not.
  • Builds a parameterized message query with optional date and ID filters plus an optional “most recent N” messageLimit by wrapping a DESC‑ordered subquery, then re‑sorting ASC.
  • Computes ThreadCloneMetadata after filtering/limiting to get an accurate lastMessageId.
  • Inserts the new thread row with JSON‑encoded metadata (including clone) and proper createdAt/updatedAt + *Z columns.
  • Clones messages inside the same transaction with new IDs, preserving content, timestamps, role/type, and using resourceId override or the source thread’s resourceId.
  • Returns fully parsed MastraDBMessages for the cloned messages.

Error handling via MastraError (including specific SOURCE_NOT_FOUND and THREAD_EXISTS codes, plus a generic FAILED wrapper) is consistent with the rest of the PG domain. I don’t see correctness gaps here.

Also applies to: 1116-1293

stores/libsql/src/storage/domains/memory/index.ts (1)

906-1087: LGTM! Well-structured cloneThread implementation.

The implementation correctly:

  • Validates source thread existence and new thread ID uniqueness
  • Uses parameterized queries for safe SQL construction
  • Applies filters (date range, messageIds) and limit correctly with the DESC/LIMIT/ASC pattern
  • Uses a transaction to ensure atomicity of thread and message creation
  • Properly re-throws MastraError instances while wrapping other errors
stores/upstash/src/storage/domains/memory/index.ts (1)

1127-1285: LGTM! Consistent implementation with appropriate Redis patterns.

The implementation:

  • Follows the same validation and error handling patterns as LibSQL
  • Uses filterByDateRange utility for consistent filtering behavior
  • Properly maintains message ordering via sorted set scores
  • Uses Redis pipeline for efficient bulk writes
  • Correctly maintains the message ID → threadId index for fast lookups
packages/memory/src/index.ts (4)

1115-1129: LGTM! Clean delegation with semantic recall integration.

The cloneThread method correctly:

  • Delegates to the storage layer for the actual cloning
  • Conditionally embeds cloned messages when semantic recall is enabled
  • Returns the complete result with thread and messages

1135-1206: Embedding logic is correct and handles edge cases appropriately.

The optional chaining (message.content?.content) is a good defensive choice here since cloned messages may have content parsed from various storage backends with potentially different structures.


1323-1340: N+1 query pattern is acceptable for typical clone depth.

The method makes one query per ancestor in the clone chain. While this is an N+1 pattern, clone chains are typically shallow (1-3 levels deep), so the impact is minimal. Consider adding a depth limit if deep cloning becomes a supported use case to prevent potential runaway queries.


1345-1347: Good practice to re-export clone-related types.

Re-exporting StorageCloneThreadInput, StorageCloneThreadOutput, and ThreadCloneMetadata from @mastra/core/storage provides a convenient single import path for consumers of the memory package.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

return null;
}
return thread.metadata.clone as ThreadCloneMetadata;
}
Copy link

Choose a reason for hiding this comment

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

Clone metadata Date not restored after JSON deserialization

The ThreadCloneMetadata type declares clonedAt: Date, but when clone metadata is stored in persistent databases (LibSQL, PG, Upstash), it goes through JSON.stringify which converts the Date to an ISO string. When the thread is read back via JSON.parse, clonedAt remains a string. The getCloneMetadata method casts the raw metadata to ThreadCloneMetadata, making TypeScript believe clonedAt is a Date when it's actually a string. This type mismatch will cause runtime errors if code attempts to call Date methods on clonedAt. The unit test passes only because it uses InMemoryStore which preserves Date objects without serialization.

Additional Locations (1)

Fix in Cursor Fix in Web

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: 0

🧹 Nitpick comments (2)
packages/memory/src/index.test.ts (2)

204-205: Consider using proper typing instead of as any.

The type assertion as any bypasses TypeScript's type checking. Consider using the getCloneMetadata() utility method (which you're already testing later) or defining a proper type for clone metadata.

🔎 Alternative approach using getCloneMetadata
-      expect(clonedThread.metadata?.clone).toBeDefined();
-      expect((clonedThread.metadata?.clone as any).sourceThreadId).toBe(sourceThread.id);
+      const cloneMetadata = memory.getCloneMetadata(clonedThread);
+      expect(cloneMetadata).toBeDefined();
+      expect(cloneMetadata?.sourceThreadId).toBe(sourceThread.id);

153-471: Comprehensive test coverage for cloneThread functionality.

The test suite thoroughly covers:

  • Basic cloning with message preservation
  • Custom titles and thread IDs
  • Message filtering (limits, date ranges, specific IDs)
  • Error handling (non-existent source, duplicate IDs)
  • Cross-resource cloning and metadata preservation
Optional: Consider adding edge case tests

Additional test cases that could further strengthen coverage:

  • Cloning an empty thread (no messages)
  • Combining messageLimit with messageFilter (e.g., limit + date range)
  • Invalid filter parameters (e.g., startDate > endDate)
  • Cloning with very large message counts

These are nice-to-have improvements rather than critical gaps.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ceb1b7 and 6780c05.

📒 Files selected for processing (1)
  • packages/memory/src/index.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Run pnpm typecheck to validate TypeScript types across all packages

Files:

  • packages/memory/src/index.test.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Run pnpm prettier:format to format code and pnpm format to run linting with auto-fix across all packages

Files:

  • packages/memory/src/index.test.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/**/*.{ts,tsx}: All packages must use TypeScript with strict type checking enabled
Use telemetry decorators for observability across components

Files:

  • packages/memory/src/index.test.ts
**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{test,spec}.{ts,tsx}: Use Vitest for testing framework in test files
Co-locate test files with source code using naming patterns like *.test.ts or *.spec.ts

Files:

  • packages/memory/src/index.test.ts
🧠 Learnings (4)
📚 Learning: 2025-11-24T16:42:04.244Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/codemod/AGENTS.md:0-0
Timestamp: 2025-11-24T16:42:04.244Z
Learning: Applies to packages/codemod/src/test/__fixtures__/**/*.ts : Create test fixtures by copying examples DIRECTLY from migration guides in `docs/src/content/en/guides/migrations/upgrade-to-v1/` without hallucinating or inventing changes

Applied to files:

  • packages/memory/src/index.test.ts
📚 Learning: 2025-11-24T16:42:04.244Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/codemod/AGENTS.md:0-0
Timestamp: 2025-11-24T16:42:04.244Z
Learning: Applies to packages/codemod/src/test/**/*.test.ts : Include test cases for multiple occurrences of the transformation pattern, aliased imports, type imports, and mixed imports to verify the codemod works consistently

Applied to files:

  • packages/memory/src/index.test.ts
📚 Learning: 2025-11-24T16:42:04.244Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/codemod/AGENTS.md:0-0
Timestamp: 2025-11-24T16:42:04.244Z
Learning: Applies to packages/codemod/src/test/__fixtures__/**/*.ts : In output fixtures, ensure all NEGATIVE test cases remain EXACTLY IDENTICAL to their input fixture counterparts to verify the codemod only transforms intended patterns

Applied to files:

  • packages/memory/src/index.test.ts
📚 Learning: 2025-11-24T16:42:04.244Z
Learnt from: CR
Repo: mastra-ai/mastra PR: 0
File: packages/codemod/AGENTS.md:0-0
Timestamp: 2025-11-24T16:42:04.244Z
Learning: Applies to packages/codemod/src/codemods/v1/**/*.ts : When transforming TypeScript type imports and usages, check the parent node type to skip transforming identifiers that are part of import declarations to avoid transforming imports from other packages with the same type name

Applied to files:

  • packages/memory/src/index.test.ts
🧬 Code graph analysis (1)
packages/memory/src/index.test.ts (2)
packages/memory/src/index.ts (1)
  • Memory (55-1341)
packages/core/src/storage/mock.ts (1)
  • InMemoryStore (28-64)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Prebuild
  • GitHub Check: test
  • GitHub Check: Lint
  • GitHub Check: test
  • GitHub Check: test (hono)
  • GitHub Check: test (express)
  • GitHub Check: test
  • GitHub Check: test
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
packages/memory/src/index.test.ts (2)

143-151: Excellent test isolation setup.

The beforeEach hooks correctly create fresh Memory instances with InMemoryStore for each test, ensuring no state leakage between tests. This is the right pattern for testing stateful components.

Also applies to: 473-481


473-701: Excellent coverage of clone utility methods.

The utility method tests are thorough and well-structured:

  • isClone: Tests positive, negative, and null cases
  • getCloneMetadata: Validates metadata retrieval with proper null handling
  • getSourceThread: Tests source retrieval for both clones and regular threads
  • listClones: Tests multiple clones and empty results
  • getCloneHistory: Tests clone chains (original → clone1 → clone2), which is particularly valuable for ensuring transitive relationships work correctly

The tests demonstrate careful attention to edge cases and defensive programming.

}

return history;
}
Copy link

Choose a reason for hiding this comment

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

Missing cycle detection causes potential infinite loop

The getCloneHistory method traverses the clone chain by following sourceThreadId references in a while loop without any cycle detection. If clone metadata is manually manipulated to create a circular reference (e.g., thread A points to thread B as its source, and thread B points to thread A), the method would loop infinitely. Adding a Set to track visited thread IDs would prevent this edge case from causing a hang or denial of service.

Fix in Cursor Fix in Web

clonedAt: Date;
/** ID of the last message included in the clone (if messages were copied) */
lastMessageId?: string;
};
Copy link

Choose a reason for hiding this comment

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

Clone metadata Date field becomes string after database retrieval

The ThreadCloneMetadata type declares clonedAt as a Date, but when threads are retrieved from SQL databases (LibSQL, PostgreSQL, Upstash), the metadata is JSON-parsed without converting ISO date strings back to Date objects. This means getCloneMetadata() returns an object where clonedAt is actually a string at runtime, despite the type saying Date. Code relying on Date methods like .getTime() would fail. The unit test checking toBeInstanceOf(Date) only passes because it uses InMemoryStore which preserves Date objects.

Additional Locations (1)

Fix in Cursor Fix in Web

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: 0

🧹 Nitpick comments (1)
docs/src/content/en/reference/server/routes.mdx (1)

156-196: Inconsistent date type representation compared to rest of document.

Lines 167-168 use Date type for startDate and endDate, but elsewhere in this document (lines 291-292), dates are documented as string with "ISO date string" comment. In JSON APIs, dates are transmitted as ISO 8601 strings, not JavaScript Date objects.

Consider using string with an "ISO date string" comment for consistency, or note that the client SDK handles the conversion.

🔎 Suggested fix for request body
   options?: {
     messageLimit?: number;        // Max messages to clone
     messageFilter?: {
-      startDate?: Date;           // Clone messages after this date
-      endDate?: Date;             // Clone messages before this date
+      startDate?: string;         // ISO date string - clone messages after this date
+      endDate?: string;           // ISO date string - clone messages before this date
       messageIds?: string[];      // Clone specific messages
     };
   };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6780c05 and e11022a.

📒 Files selected for processing (5)
  • docs/src/content/en/reference/client-js/memory.mdx
  • docs/src/content/en/reference/memory/clone-utilities.mdx
  • docs/src/content/en/reference/memory/cloneThread.mdx
  • docs/src/content/en/reference/memory/memory-class.mdx
  • docs/src/content/en/reference/server/routes.mdx
✅ Files skipped from review due to trivial changes (3)
  • docs/src/content/en/reference/memory/cloneThread.mdx
  • docs/src/content/en/reference/client-js/memory.mdx
  • docs/src/content/en/reference/memory/memory-class.mdx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{md,mdx}

📄 CodeRabbit inference engine (.cursor/rules/writing-documentation.mdc)

**/*.{md,mdx}: When writing developer documentation, do not use adjectives like 'powerful' or 'built-in' as these read like marketing copy and developers don't like that
When writing developer documentation, do not use 'complete', 'out-of-the-box', 'hands-on', or overly enthusiastic exhortations like 'Check out', 'Learn more', 'Explore'. Do not use words like 'essential' or 'offers'
When writing developer documentation, do not use 'your needs', 'production-ready', 'makes it easy', or 'choose the right...solution' as these are marketing jargon that developers dislike
When writing developer documentation, avoid phrasing like 'without changing your code' or 'automatically handles' that obscures implementation details
In developer documentation, avoid phrasing that glides between benefits without diving into details. Focus on technical specifics and implementation details rather than high-level benefits. For example, avoid sentences like: 'This makes it easy to build AI applications that maintain meaningful conversations and remember important details, whether you're building a simple chatbot or a sophisticated AI assistant'
All H1 headings (# Heading) must use title case format, capitalizing the first letter of each major word. Examples: 'Getting Started', 'Human In-the-Loop Workflow', 'Agent as a Step'

Files:

  • docs/src/content/en/reference/memory/clone-utilities.mdx
  • docs/src/content/en/reference/server/routes.mdx
**/*{docs,documentation}/**/*.{md,mdx}

📄 CodeRabbit inference engine (.windsurfrules)

**/*{docs,documentation}/**/*.{md,mdx}: When writing developer documentation, do not use adjectives like 'powerful' or 'built-in' as they read like marketing copy
When writing developer documentation, do not use words like 'complete', 'out-of-the-box', 'hands-on', or overly enthusiastic exhortations such as 'Check out', 'Learn more', 'Explore', 'essential', or 'offers'
When writing developer documentation, avoid marketing jargon such as 'your needs', 'production-ready', 'makes it easy', or 'choose the right...solution'
When writing developer documentation, do not use phrases like 'without changing your code' or 'automatically handles' as they glide over implementation details
In developer documentation, avoid phrasing that glides between benefits without diving into details; instead, focus on technical nuts and bolts with specific implementation details rather than abstract benefits

Files:

  • docs/src/content/en/reference/memory/clone-utilities.mdx
  • docs/src/content/en/reference/server/routes.mdx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Validate build outputs
  • GitHub Check: Cursor Bugbot
  • GitHub Check: test
  • GitHub Check: test (express)
  • GitHub Check: test
  • GitHub Check: test (hono)
  • GitHub Check: test
  • GitHub Check: test
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
docs/src/content/en/reference/memory/clone-utilities.mdx (1)

1-345: Documentation looks good overall.

The documentation follows coding guidelines—no marketing language detected, H1 heading uses title case, and code examples are clear and technically accurate. The API surface documented here aligns with the clone utilities described in the PR.

docs/src/content/en/reference/server/routes.mdx (1)

142-142: Route table entry looks correct.

The new clone endpoint is properly documented in the Memory routes table, consistent with the route structure used elsewhere.

@abhiaiyer91 abhiaiyer91 merged commit 58e3931 into main Dec 31, 2025
46 of 50 checks passed
@abhiaiyer91 abhiaiyer91 deleted the feat/memory/branching branch December 31, 2025 19:55
metadata: {
...metadata,
clone: cloneMetadata,
},
Copy link

Choose a reason for hiding this comment

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

Source thread metadata not merged during clone operation

The documentation states that the metadata parameter will be "merged with the source thread's metadata", but the implementation only spreads the user-provided metadata without including sourceThread.metadata. This means any existing metadata on the source thread is lost during cloning unless the caller explicitly re-passes it. The clone metadata construction uses { ...metadata, clone: cloneMetadata } but is missing ...sourceThread.metadata as the first spread to preserve original metadata.

Additional Locations (2)

Fix in Cursor Fix in Web

if (result?.thread?.id) {
navigate(paths.agentThreadLink(agentId, result.thread.id));
}
}, [threadId, agentId, cloneThread, navigate, paths]);
Copy link

Choose a reason for hiding this comment

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

Unhandled promise rejection in clone thread handler

The handleCloneThread callback awaits cloneThread() (mutateAsync) without a try-catch block. While the mutation's onError callback shows a toast, mutateAsync still rejects the promise when an error occurs. This can result in unhandled promise rejection warnings in the browser console. The async function needs error handling to prevent the rejection from propagating.

Fix in Cursor Fix in Web

astout55555 pushed a commit to astout55555/mastra that referenced this pull request Jan 6, 2026
Adds thread cloning to create independent copies of conversations that
can diverge.

<img width="1450" height="785" alt="image"
src="https://github.com/user-attachments/assets/c24435f8-5410-4e37-93eb-03a9940de78c"
/>

```typescript
// Clone a thread
const { thread, clonedMessages } = await memory.cloneThread({
  sourceThreadId: 'thread-123',
  title: 'My Clone',
  options: {
    messageLimit: 10, // optional: only copy last N messages
  },
});

// Check if a thread is a clone
if (memory.isClone(thread)) {
  const source = await memory.getSourceThread(thread.id);
}

// List all clones of a thread
const clones = await memory.listClones('thread-123');
```

Includes:
- Storage implementations for InMemory, PostgreSQL, LibSQL, Upstash
- API endpoint: `POST /api/memory/threads/:threadId/clone`
- Embeddings created for cloned messages (semantic recall)
- Clone button in playground UI Memory tab
- Unit and integration tests

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds end-to-end support for cloning conversation threads, enabling
independent branches of a conversation.
> 
> - Core: `Memory.cloneThread()` plus utilities (`isClone`,
`getCloneMetadata`, `getSourceThread`, `listClones`, `getCloneHistory`);
embeddings generated for cloned messages when semantic recall is enabled
> - Storage: implementations for InMemory, PostgreSQL, LibSQL, and
Upstash; new types (`StorageCloneThreadInput/Output`,
`ThreadCloneMetadata`)
> - Server: new endpoint `POST /api/memory/threads/:threadId/clone` with
schemas and route wiring
> - Client SDK: `thread.clone(params)` and related types
(`CloneMemoryThreadParams/Response`)
> - UI: Clone button in playground Memory tab with navigation to the new
thread
> - Docs: references for client SDK, `cloneThread`, clone utilities, and
server routes
> - Tests: unit and integration coverage for cloning behavior, filters,
limits, metadata, and embeddings
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e11022a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Clone memory threads into independent copies with optional message
filtering/limits, custom IDs/titles, and embeddings for cloned messages
* Clone utilities: detect clones, retrieve source thread, list clones,
and view clone history
* API endpoint and a "Clone Thread" button in the playground Memory tab

* **Tests**
* Extensive integration and unit tests covering cloning scenarios,
filters, limits, metadata, and embeddings

* **Documentation**
  * Added changelog and docs for cloneThread and clone utilities

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
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