refactor(integrations): rename dsh-mem0 to deepseek-plugin, strands-mem0 to mem0-strands (#7098)
This commit is contained in:
@@ -9,12 +9,12 @@ Agent and editor integrations. Each subdirectory is self-contained: its own `pac
|
||||
| `mem0-plugin/` | Claude Code / Cursor / Codex plugin | none | none | pytest |
|
||||
| `mem0-plugin/.opencode-plugin/` | `@mem0/opencode-plugin` | Bun | none | tsc type-check |
|
||||
| `pi-agent-plugin/` | `@mem0/pi-agent-plugin` | tsup | none | vitest |
|
||||
| `dsh-mem0/` | `@mem0/dsh-mem0` | tsup (ESM) | none | vitest |
|
||||
| `deepseek-plugin/` | `@mem0/deepseek-plugin` | tsup (ESM) | none | vitest |
|
||||
| `n8n-nodes-mem0/` | `@mem0/n8n-nodes-mem0` | tsc | ESLint (n8n-nodes-base) | none |
|
||||
| `zapier-mem0/` | `@mem0/zapier` | tsc | none | offline unit tests + `zapier validate` |
|
||||
| `strands-mem0/` | `strands-mem0` (PyPI) | hatch | Ruff + mypy | pytest |
|
||||
| `mem0-strands/` | `mem0-strands` (PyPI) | hatch | Ruff + mypy | pytest |
|
||||
|
||||
pnpm everywhere except `.opencode-plugin/` (Bun) and `strands-mem0/` (Python: pip / hatch). Never npm, never yarn.
|
||||
pnpm everywhere except `.opencode-plugin/` (Bun) and `mem0-strands/` (Python: pip / hatch). Never npm, never yarn.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -41,10 +41,10 @@ Run the type check after every TypeScript change: `pnpm run typecheck` or `tsc -
|
||||
|
||||
- **`vercel-ai-sdk/`** wraps the Vercel AI SDK through a `createMem0` provider. Integrations for AI-SDK repos go through this wrapper, not raw `MemoryClient`.
|
||||
- **`mem0-plugin/`** connects Claude Code, Cursor, and Codex to the MCP server at `mcp.mem0.ai` and installs lifecycle hooks for automatic memory capture. Exposes 9 MCP tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`.
|
||||
- **`openclaw/`**, **`pi-agent-plugin/`**, **`dsh-mem0/`** are editor and agent plugins with the same shape. `dsh-mem0/` registers Mem0 search/add tools as a native DeepSeek Harness (Cordis) plugin.
|
||||
- **`openclaw/`**, **`pi-agent-plugin/`**, **`deepseek-plugin/`** are editor and agent plugins with the same shape. `deepseek-plugin/` registers Mem0 search/add tools as a native DeepSeek Harness (Cordis) plugin.
|
||||
- **`n8n-nodes-mem0/`** is an n8n community node: add, search, get, update, delete.
|
||||
- **`zapier-mem0/`** is a Zapier Platform CLI app: add, search, get, delete. It deploys to Zapier, not npm, so it is **not** in the release router. Deploy it with `gh workflow run zapier-mem0-cd.yml --ref main` (needs the `ZAPIER_DEPLOY_KEY` secret).
|
||||
- **`strands-mem0/`** is a native Strands `MemoryStore` (Python, published to PyPI as `strands-mem0`). It plugs into the Strands `MemoryManager` for automatic recall and server-side extraction, over the hosted Mem0 platform or self-hosted Mem0 OSS. The package lives under `strands-mem0/python/`.
|
||||
- **`mem0-strands/`** is a native Strands `MemoryStore` (Python, published to PyPI as `mem0-strands`). It plugs into the Strands `MemoryManager` for automatic recall and server-side extraction, over the hosted Mem0 platform or self-hosted Mem0 OSS. The package lives under `mem0-strands/python/`.
|
||||
|
||||
## Adding an integration
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# dsh-mem0
|
||||
# deepseek-plugin
|
||||
|
||||
[Mem0](https://mem0.ai) long-term memory as a native [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (Cordis) plugin.
|
||||
|
||||
@@ -18,7 +18,7 @@ A Cordis plugin is a module exporting `apply(ctx, config)`. This one declares `i
|
||||
```
|
||||
[ mem0ai SDK ] <-- managed memory, owned by Mem0
|
||||
|
|
||||
[ dsh-mem0: apply(ctx) -> ctx.tools.register(...) ] <-- this package
|
||||
[ deepseek-plugin: apply(ctx) -> ctx.tools.register(...) ] <-- this package
|
||||
|
|
||||
[ DeepSeek Harness ] <-- the agent, loaded via cordis.yml
|
||||
```
|
||||
@@ -27,7 +27,7 @@ A Cordis plugin is a module exporting `apply(ctx, config)`. This one declares `i
|
||||
|
||||
1. Build the plugin:
|
||||
```sh
|
||||
cd integrations/dsh-mem0
|
||||
cd integrations/deepseek-plugin
|
||||
pnpm install
|
||||
pnpm build
|
||||
```
|
||||
@@ -37,7 +37,7 @@ A Cordis plugin is a module exporting `apply(ctx, config)`. This one declares `i
|
||||
```
|
||||
3. Point Harness at it. Copy `cordis.example.yml`, set the absolute path to `dist/index.js` and your `userId`, then:
|
||||
```sh
|
||||
pnpm dsh web --patch ./integrations/dsh-mem0/cordis.example.yml
|
||||
pnpm dsh web --patch ./integrations/deepseek-plugin/cordis.example.yml
|
||||
```
|
||||
4. Open http://127.0.0.1:3080 and ask the agent to remember something, then recall it in a later turn.
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
# Example DeepSeek Harness config that loads dsh-mem0 alongside the built-in
|
||||
# Example DeepSeek Harness config that loads deepseek-plugin alongside the built-in
|
||||
# tools plugin. Load with:
|
||||
#
|
||||
# pnpm dsh web --patch ./integrations/dsh-mem0/cordis.example.yml
|
||||
# pnpm dsh web --patch ./integrations/deepseek-plugin/cordis.example.yml
|
||||
#
|
||||
# The tools plugin (and its system-prompt dependency) must be present, because
|
||||
# the memory tools contribute schemas the system prompt renders.
|
||||
@@ -12,7 +12,7 @@
|
||||
- id: mem0
|
||||
# Absolute path to the built plugin (run `pnpm build` first), or point
|
||||
# at src/index.ts when running through tsx during development.
|
||||
name: "/absolute/path/to/mem0/integrations/dsh-mem0/dist/index.js"
|
||||
name: "/absolute/path/to/mem0/integrations/deepseek-plugin/dist/index.js"
|
||||
config:
|
||||
# apiKey is read from the MEM0_API_KEY env var when omitted here.
|
||||
userId: "your-user-id"
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@mem0/dsh-mem0",
|
||||
"name": "@mem0/deepseek-plugin",
|
||||
"version": "0.1.0",
|
||||
"description": "Mem0 long-term memory as a native DeepSeek Harness (Cordis) plugin.",
|
||||
"type": "module",
|
||||
@@ -7,7 +7,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mem0ai/mem0",
|
||||
"directory": "integrations/dsh-mem0"
|
||||
"directory": "integrations/deepseek-plugin"
|
||||
},
|
||||
"keywords": [
|
||||
"deepseek-harness",
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* dsh-mem0: Mem0 long-term memory as a native DeepSeek Harness (Cordis) plugin.
|
||||
* deepseek-plugin: Mem0 long-term memory as a native DeepSeek Harness (Cordis) plugin.
|
||||
*
|
||||
* Registers two agent-callable tools backed by the Mem0 SDK:
|
||||
* - `search_memory` recalls facts relevant to a query
|
||||
@@ -69,11 +69,11 @@ const scopeParams = {
|
||||
export function apply(ctx: Context, config: Config): void {
|
||||
const apiKey = config.apiKey ?? process.env.MEM0_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("dsh-mem0: set config.apiKey or the MEM0_API_KEY env var");
|
||||
throw new Error("deepseek-plugin: set config.apiKey or the MEM0_API_KEY env var");
|
||||
}
|
||||
const userId = config.userId;
|
||||
if (!userId) {
|
||||
throw new Error("dsh-mem0: config.userId is required");
|
||||
throw new Error("deepseek-plugin: config.userId is required");
|
||||
}
|
||||
|
||||
const client = new MemoryClient({
|
||||
@@ -1,4 +1,4 @@
|
||||
strands-mem0
|
||||
mem0-strands
|
||||
Copyright 2026 Mem0
|
||||
|
||||
This product includes software developed at Mem0 (https://mem0.ai).
|
||||
@@ -1,5 +1,5 @@
|
||||
<div align="center">
|
||||
<h1>strands-mem0</h1>
|
||||
<h1>mem0-strands</h1>
|
||||
<h3>Persistent long-term memory for Strands Agents, backed by Mem0</h3>
|
||||
<p>
|
||||
A community <a href="https://strandsagents.com/">Strands Agents</a> integration that plugs
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
---
|
||||
|
||||
`strands-mem0` gives [Strands](https://github.com/strands-agents/sdk-python) agents durable memory
|
||||
`mem0-strands` gives [Strands](https://github.com/strands-agents/sdk-python) agents durable memory
|
||||
that survives across sessions, backed by [Mem0](https://mem0.ai). Where the
|
||||
`mem0_memory` tool is called explicitly by the model, `Mem0MemoryStore` plugs into the **agent loop**
|
||||
directly: the manager recalls context and injects it automatically, and writes new memories, either
|
||||
@@ -22,7 +22,7 @@ verbatim or by extracting facts from the conversation.
|
||||
## Install
|
||||
|
||||
```bash
|
||||
pip install strands-mem0
|
||||
pip install mem0-strands
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -30,7 +30,7 @@ pip install strands-mem0
|
||||
```python
|
||||
from strands import Agent
|
||||
from strands.memory import MemoryManager
|
||||
from strands_mem0 import Mem0MemoryStore
|
||||
from mem0_strands import Mem0MemoryStore
|
||||
|
||||
# Recall + write, distilling facts from the conversation via Mem0's server-side extraction.
|
||||
store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True)
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
# strands-mem0 (Python)
|
||||
# mem0-strands (Python)
|
||||
|
||||
Persistent long-term memory for [Strands Agents](https://github.com/strands-agents/sdk-python),
|
||||
backed by [Mem0](https://mem0.ai).
|
||||
@@ -6,7 +6,7 @@ backed by [Mem0](https://mem0.ai).
|
||||
See the [repository README](../README.md) for full usage. Quick start:
|
||||
|
||||
```bash
|
||||
pip install strands-mem0
|
||||
pip install mem0-strands
|
||||
```
|
||||
|
||||
As a `MemoryStore` that plugs into the agent loop (Strands >= 1.45):
|
||||
@@ -14,7 +14,7 @@ As a `MemoryStore` that plugs into the agent loop (Strands >= 1.45):
|
||||
```python
|
||||
from strands import Agent
|
||||
from strands.memory import MemoryManager
|
||||
from strands_mem0 import Mem0MemoryStore
|
||||
from mem0_strands import Mem0MemoryStore
|
||||
|
||||
store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True)
|
||||
agent = Agent(memory_manager=MemoryManager(stores=[store]))
|
||||
@@ -32,6 +32,6 @@ hatch run prepare # format + lint + typecheck + test
|
||||
|
||||
## Release
|
||||
|
||||
Publish a GitHub release tagged `strands-mem0-v*` (e.g. `strands-mem0-v0.1.0`). The
|
||||
release router (`.github/workflows/release.yml`) dispatches `strands-mem0-cd.yml`,
|
||||
Publish a GitHub release tagged `mem0-strands-v*` (e.g. `mem0-strands-v0.1.0`). The
|
||||
release router (`.github/workflows/release.yml`) dispatches `mem0-strands-cd.yml`,
|
||||
which builds the wheel and publishes it to PyPI via trusted publishing (OIDC).
|
||||
+3
-3
@@ -3,7 +3,7 @@ requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "strands-mem0"
|
||||
name = "mem0-strands"
|
||||
version = "0.1.0"
|
||||
description = "Persistent long-term memory for Strands agents, backed by Mem0."
|
||||
readme = "README.md"
|
||||
@@ -33,7 +33,7 @@ dependencies = [
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://mem0.ai"
|
||||
Documentation = "https://github.com/mem0ai/mem0/tree/main/integrations/strands-mem0#readme"
|
||||
Documentation = "https://github.com/mem0ai/mem0/tree/main/integrations/mem0-strands#readme"
|
||||
Repository = "https://github.com/mem0ai/mem0"
|
||||
Issues = "https://github.com/mem0ai/mem0/issues"
|
||||
|
||||
@@ -47,7 +47,7 @@ dev = [
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/strands_mem0"]
|
||||
packages = ["src/mem0_strands"]
|
||||
|
||||
[tool.hatch.envs.default]
|
||||
dependencies = [
|
||||
+3
-3
@@ -12,8 +12,8 @@ share one Mem0 backend and namespace.
|
||||
|
||||
from importlib.metadata import PackageNotFoundError, version
|
||||
|
||||
from strands_mem0.client import Mem0ServiceClient
|
||||
from strands_mem0.store import Mem0MemoryStore
|
||||
from mem0_strands.client import Mem0ServiceClient
|
||||
from mem0_strands.store import Mem0MemoryStore
|
||||
|
||||
__all__ = [
|
||||
"Mem0MemoryStore",
|
||||
@@ -21,6 +21,6 @@ __all__ = [
|
||||
]
|
||||
|
||||
try:
|
||||
__version__ = version("strands-mem0")
|
||||
__version__ = version("mem0-strands")
|
||||
except PackageNotFoundError: # pragma: no cover - only when running from a source tree
|
||||
__version__ = "0.0.0+unknown"
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
"""A thin wrapper around the Mem0 SDK used by :class:`~strands_mem0.store.Mem0MemoryStore`.
|
||||
"""A thin wrapper around the Mem0 SDK used by :class:`~mem0_strands.store.Mem0MemoryStore`.
|
||||
|
||||
Both Mem0 backends -- the hosted platform (:class:`mem0.MemoryClient`) and
|
||||
self-hosted OSS (:class:`mem0.Memory`) -- expose the same call shape to the store:
|
||||
@@ -95,7 +95,7 @@ class Mem0ServiceClient:
|
||||
from mem0 import Memory
|
||||
except ImportError as err: # pragma: no cover - exercised via install docs
|
||||
raise ImportError(
|
||||
"The mem0ai package is required. Install it with: pip install 'strands-mem0'"
|
||||
"The mem0ai package is required. Install it with: pip install 'mem0-strands'"
|
||||
) from err
|
||||
self.mem0 = Memory.from_config(config)
|
||||
self.is_platform = False
|
||||
@@ -104,7 +104,7 @@ class Mem0ServiceClient:
|
||||
try:
|
||||
from mem0 import MemoryClient
|
||||
except ImportError as err: # pragma: no cover - exercised via install docs
|
||||
raise ImportError("The mem0ai package is required. Install it with: pip install 'strands-mem0'") from err
|
||||
raise ImportError("The mem0ai package is required. Install it with: pip install 'mem0-strands'") from err
|
||||
api_key = api_key or os.environ.get("MEM0_API_KEY")
|
||||
# MemoryClient(host=None) would override the SDK default with None, so only
|
||||
# pass host when the caller actually set one.
|
||||
+3
-3
@@ -21,7 +21,7 @@ Example:
|
||||
```python
|
||||
from strands import Agent
|
||||
from strands.memory import MemoryManager
|
||||
from strands_mem0 import Mem0MemoryStore
|
||||
from mem0_strands import Mem0MemoryStore
|
||||
|
||||
# Recall + write, with Mem0 extracting facts from the conversation server-side.
|
||||
store = Mem0MemoryStore(user_id="alex", writable=True, extraction=True)
|
||||
@@ -41,7 +41,7 @@ from typing import Any
|
||||
from strands.memory import AddMessagesContext, MemoryEntry, MemoryStore, SearchOptions
|
||||
from strands.types.content import Message
|
||||
|
||||
from strands_mem0.client import Mem0ServiceClient
|
||||
from mem0_strands.client import Mem0ServiceClient
|
||||
|
||||
DEFAULT_MAX_SEARCH_RESULTS = 5
|
||||
# Entity fields that scope a memory in Mem0. At least one must be set.
|
||||
@@ -92,7 +92,7 @@ class Mem0MemoryStore(MemoryStore):
|
||||
api_key: Mem0 platform API key (defaults to ``$MEM0_API_KEY``).
|
||||
host: Mem0 platform base URL.
|
||||
config: Mem0 OSS config dict for a self-hosted backend.
|
||||
client: A pre-built :class:`~strands_mem0.client.Mem0ServiceClient`
|
||||
client: A pre-built :class:`~mem0_strands.client.Mem0ServiceClient`
|
||||
(for testing, or to wrap your own raw Mem0 client via
|
||||
``Mem0ServiceClient(client=...)``); when omitted, one is
|
||||
constructed lazily on first use from ``api_key`` / ``config``.
|
||||
+1
-1
@@ -8,7 +8,7 @@ what the earlier permissive fakes did not do.
|
||||
|
||||
import pytest
|
||||
|
||||
from strands_mem0.client import Mem0ServiceClient, _extract_results, _is_platform_client
|
||||
from mem0_strands.client import Mem0ServiceClient, _extract_results, _is_platform_client
|
||||
|
||||
|
||||
class FakeMemoryClient:
|
||||
+2
-2
@@ -10,7 +10,7 @@ import pytest
|
||||
from strands.memory import MemoryEntry, MemoryStore
|
||||
from strands.memory.types import _has_method, _has_write_sink
|
||||
|
||||
from strands_mem0 import Mem0MemoryStore
|
||||
from mem0_strands import Mem0MemoryStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -241,7 +241,7 @@ def test_client_constructed_lazily(monkeypatch):
|
||||
calls["n"] += 1
|
||||
self.api_key = api_key
|
||||
|
||||
monkeypatch.setattr("strands_mem0.store.Mem0ServiceClient", FakeClient)
|
||||
monkeypatch.setattr("mem0_strands.store.Mem0ServiceClient", FakeClient)
|
||||
|
||||
store = Mem0MemoryStore(user_id="alex", api_key="m0-x")
|
||||
assert calls["n"] == 0 # not built yet
|
||||
Reference in New Issue
Block a user