Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f681889b14 | ||
|
|
b5ec46be5b | ||
|
|
168ad358d5 | ||
|
|
2c796d144f | ||
|
|
c676c2c458 | ||
|
|
b36847622d | ||
|
|
32c8849044 | ||
|
|
2dd2872c08 | ||
|
|
cf268da19d | ||
|
|
7a5df64746 | ||
|
|
4c41f6deeb | ||
|
|
f84aa1eb31 | ||
|
|
9226ee2229 | ||
|
|
8399b088a5 | ||
|
|
437f0b5495 |
@@ -8,7 +8,7 @@
|
||||
"name": "mem0",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./mem0-plugin"
|
||||
"path": "./integrations/mem0-plugin"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "mem0",
|
||||
"source": "./mem0-plugin",
|
||||
"source": "./integrations/mem0-plugin",
|
||||
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search to Claude workflows.",
|
||||
"version": "0.2.9"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"name": "mem0",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./mem0-plugin"
|
||||
"path": "./integrations/mem0-plugin"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "mem0",
|
||||
"source": "./mem0-plugin",
|
||||
"source": "./integrations/mem0-plugin",
|
||||
"description": "Mem0 memory layer for AI applications. Add persistent memory, personalization, and semantic search.",
|
||||
"version": "0.2.9"
|
||||
}
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged v* is
|
||||
# published. Can also be dispatched manually to re-publish a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. v1.2.3)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Unused for PyPI (pre-releases are expressed in the version itself); accepted for router uniformity'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
|
||||
# Pure SDK version tags only (v1.2.3) — excludes package-prefixed tags
|
||||
# like vercel-ai-v* that also start with 'v'
|
||||
if: startsWith(github.event.release.tag_name, 'v') && !contains(github.event.release.tag_name, '-v')
|
||||
if: startsWith(inputs.tag, 'v') && !contains(inputs.tag, '-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
@@ -41,7 +54,6 @@ jobs:
|
||||
# packages_dir: dist/
|
||||
|
||||
- name: Publish distribution 📦 to PyPI
|
||||
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-v')
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
packages_dir: dist/
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
name: CI Gate
|
||||
|
||||
# Single required status check for all PRs.
|
||||
#
|
||||
# Path-filtered CI workflows can't be marked as required in branch
|
||||
# protection: on a PR that doesn't touch their paths they never report, and
|
||||
# the required check hangs at "Expected" forever. This gate solves that. It
|
||||
# runs on every PR, detects which packages changed, calls only the relevant
|
||||
# package CI workflows (as reusable workflows), and the final "CI Gate" job
|
||||
# reports the aggregate result — success when every invoked pipeline passed
|
||||
# (skipped pipelines are fine), failure when any failed.
|
||||
#
|
||||
# Branch protection should require exactly one status check: "CI Gate".
|
||||
#
|
||||
# Package CI workflows keep their own push-to-main and workflow_dispatch
|
||||
# triggers; only their pull_request triggers moved here. To wire in a new
|
||||
# package: add a filter under the `changes` job, a call job that `uses:` the
|
||||
# package workflow, and list the call job in the gate's `needs`.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ci-gate-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
name: Detect changed packages
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
python_sdk: ${{ steps.filter.outputs.python_sdk }}
|
||||
ts_sdk: ${{ steps.filter.outputs.ts_sdk }}
|
||||
cli_python: ${{ steps.filter.outputs.cli_python }}
|
||||
cli_node: ${{ steps.filter.outputs.cli_node }}
|
||||
openclaw: ${{ steps.filter.outputs.openclaw }}
|
||||
opencode_plugin: ${{ steps.filter.outputs.opencode_plugin }}
|
||||
pi_agent_plugin: ${{ steps.filter.outputs.pi_agent_plugin }}
|
||||
docs_llms_txt: ${{ steps.filter.outputs.docs_llms_txt }}
|
||||
steps:
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
with:
|
||||
# Each filter mirrors the package workflow's old pull_request
|
||||
# paths, plus the package workflow file itself and this gate file
|
||||
# (changing either must re-exercise the pipeline).
|
||||
filters: |
|
||||
python_sdk:
|
||||
- 'mem0/**'
|
||||
- 'tests/**'
|
||||
- 'pyproject.toml'
|
||||
- '.github/workflows/ci.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
ts_sdk:
|
||||
- 'mem0-ts/**'
|
||||
- '.github/workflows/ts-sdk-ci.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
cli_python:
|
||||
- 'cli/python/**'
|
||||
- '.github/workflows/cli-python-ci.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
cli_node:
|
||||
- 'cli/node/**'
|
||||
- '.github/workflows/cli-node-ci.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
openclaw:
|
||||
- 'integrations/openclaw/**'
|
||||
- '.github/workflows/openclaw-checks.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
opencode_plugin:
|
||||
- 'integrations/mem0-plugin/.opencode-plugin/**'
|
||||
- '.github/workflows/opencode-plugin-checks.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
pi_agent_plugin:
|
||||
- 'integrations/pi-agent-plugin/**'
|
||||
- '.github/workflows/pi-agent-plugin-checks.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
docs_llms_txt:
|
||||
- 'docs/**/*.mdx'
|
||||
- 'docs/llms.txt'
|
||||
- 'scripts/check-llms-txt-coverage.py'
|
||||
- 'scripts/llms-txt-ignore.txt'
|
||||
- '.github/workflows/docs-llms-txt-check.yml'
|
||||
- '.github/workflows/ci-gate.yml'
|
||||
|
||||
python-sdk:
|
||||
name: Python SDK
|
||||
needs: changes
|
||||
if: needs.changes.outputs.python_sdk == 'true'
|
||||
uses: ./.github/workflows/ci.yml
|
||||
secrets: inherit
|
||||
|
||||
ts-sdk:
|
||||
name: TypeScript SDK
|
||||
needs: changes
|
||||
if: needs.changes.outputs.ts_sdk == 'true'
|
||||
uses: ./.github/workflows/ts-sdk-ci.yml
|
||||
secrets: inherit
|
||||
|
||||
cli-python:
|
||||
name: Python CLI
|
||||
needs: changes
|
||||
if: needs.changes.outputs.cli_python == 'true'
|
||||
uses: ./.github/workflows/cli-python-ci.yml
|
||||
secrets: inherit
|
||||
|
||||
cli-node:
|
||||
name: Node CLI
|
||||
needs: changes
|
||||
if: needs.changes.outputs.cli_node == 'true'
|
||||
uses: ./.github/workflows/cli-node-ci.yml
|
||||
secrets: inherit
|
||||
|
||||
openclaw:
|
||||
name: OpenClaw
|
||||
needs: changes
|
||||
if: needs.changes.outputs.openclaw == 'true'
|
||||
uses: ./.github/workflows/openclaw-checks.yml
|
||||
secrets: inherit
|
||||
|
||||
opencode-plugin:
|
||||
name: OpenCode Plugin
|
||||
needs: changes
|
||||
if: needs.changes.outputs.opencode_plugin == 'true'
|
||||
uses: ./.github/workflows/opencode-plugin-checks.yml
|
||||
secrets: inherit
|
||||
|
||||
pi-agent-plugin:
|
||||
name: Pi Agent Plugin
|
||||
needs: changes
|
||||
if: needs.changes.outputs.pi_agent_plugin == 'true'
|
||||
uses: ./.github/workflows/pi-agent-plugin-checks.yml
|
||||
secrets: inherit
|
||||
|
||||
docs-llms-txt:
|
||||
name: docs llms.txt
|
||||
needs: changes
|
||||
if: needs.changes.outputs.docs_llms_txt == 'true'
|
||||
uses: ./.github/workflows/docs-llms-txt-check.yml
|
||||
secrets: inherit
|
||||
|
||||
gate:
|
||||
name: CI Gate
|
||||
needs:
|
||||
- changes
|
||||
- python-sdk
|
||||
- ts-sdk
|
||||
- cli-python
|
||||
- cli-node
|
||||
- openclaw
|
||||
- opencode-plugin
|
||||
- pi-agent-plugin
|
||||
- docs-llms-txt
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Evaluate pipeline results
|
||||
env:
|
||||
NEEDS: ${{ toJSON(needs) }}
|
||||
run: |
|
||||
echo "$NEEDS" | jq -r 'to_entries[] | "\(.key): \(.value.result)"'
|
||||
failed=$(echo "$NEEDS" | jq -r '[to_entries[] | select(.value.result == "failure" or .value.result == "cancelled") | .key] | join(", ")')
|
||||
if [ -n "$failed" ]; then
|
||||
echo "::error::Failing pipelines: $failed"
|
||||
exit 1
|
||||
fi
|
||||
echo "All pipelines relevant to this change passed."
|
||||
@@ -1,9 +1,11 @@
|
||||
name: ci
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# push-to-main runs remain standalone.
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
changelog_check:
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
name: Publish @mem0/cli 📦 to npm
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged
|
||||
# cli-node-v* is published. Can also be dispatched manually to re-publish
|
||||
# a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. cli-node-v0.2.0)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Publish under the version preid dist-tag instead of latest'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish @mem0/cli 📦 to npm
|
||||
if: startsWith(github.event.release.tag_name, 'cli-node-v')
|
||||
if: startsWith(inputs.tag, 'cli-node-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
@@ -16,6 +28,8 @@ jobs:
|
||||
working-directory: cli/node
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
@@ -38,7 +52,7 @@ jobs:
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
|
||||
if [ "${{ inputs.prerelease }}" = "true" ]; then
|
||||
PREID=$(node -p "require('./package.json').version.split('-')[1].split('.')[0]")
|
||||
npx npm@latest publish --provenance --access public --tag "$PREID"
|
||||
else
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
name: CLI Node CI
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# push-to-main and manual runs remain standalone.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
@@ -7,10 +9,7 @@ on:
|
||||
paths:
|
||||
- 'cli/node/**'
|
||||
- '.github/workflows/cli-node-ci.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'cli/node/**'
|
||||
- '.github/workflows/cli-node-ci.yml'
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
name: Publish mem0-cli 🐍 distributions 📦 to PyPI
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged cli-v* is
|
||||
# published. Can also be dispatched manually to re-publish a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. cli-v0.2.0)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Unused for PyPI (pre-releases are expressed in the version itself); accepted for router uniformity'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish mem0-cli 📦 to PyPI
|
||||
if: startsWith(github.event.release.tag_name, 'cli-v')
|
||||
if: startsWith(inputs.tag, 'cli-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
@@ -16,6 +27,8 @@ jobs:
|
||||
working-directory: cli/python
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
name: CLI Python CI
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# push-to-main and manual runs remain standalone.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
@@ -7,10 +9,7 @@ on:
|
||||
paths:
|
||||
- 'cli/python/**'
|
||||
- '.github/workflows/cli-python-ci.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'cli/python/**'
|
||||
- '.github/workflows/cli-python-ci.yml'
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
||||
@@ -6,13 +6,10 @@ name: docs - llms.txt check
|
||||
# python scripts/check-llms-txt-coverage.py # read-only
|
||||
# python scripts/check-llms-txt-coverage.py --write # scaffold placeholders
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# manual runs remain standalone.
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**/*.mdx'
|
||||
- 'docs/llms.txt'
|
||||
- 'scripts/check-llms-txt-coverage.py'
|
||||
- 'scripts/llms-txt-ignore.txt'
|
||||
workflow_call:
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
name: Publish @mem0/openclaw-mem0 📦 to npm
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged
|
||||
# openclaw-v* is published. Can also be dispatched manually to re-publish
|
||||
# a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. openclaw-v0.5.0)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Publish under the version preid dist-tag instead of latest'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish @mem0/openclaw-mem0 📦 to npm
|
||||
if: startsWith(github.event.release.tag_name, 'openclaw-v')
|
||||
if: startsWith(inputs.tag, 'openclaw-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
defaults:
|
||||
run:
|
||||
working-directory: openclaw
|
||||
working-directory: integrations/openclaw
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
@@ -28,7 +42,7 @@ jobs:
|
||||
node-version: '22'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: openclaw/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -38,7 +52,7 @@ jobs:
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
|
||||
if [ "${{ inputs.prerelease }}" = "true" ]; then
|
||||
PREID=$(node -p "require('./package.json').version.split('-')[1].split('.')[0]")
|
||||
npx npm@latest publish --provenance --access public --tag "$PREID"
|
||||
else
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
name: openclaw checks
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# push-to-main and manual runs remain standalone.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'openclaw/**'
|
||||
- '.github/workflows/openclaw-checks.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'openclaw/**'
|
||||
- 'integrations/openclaw/**'
|
||||
- '.github/workflows/openclaw-checks.yml'
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
@@ -28,13 +27,13 @@ jobs:
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: openclaw/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd openclaw && pnpm install --frozen-lockfile
|
||||
run: cd integrations/openclaw && pnpm install --frozen-lockfile
|
||||
|
||||
- name: Type check
|
||||
run: cd openclaw && pnpm exec tsc --noEmit
|
||||
run: cd integrations/openclaw && pnpm exec tsc --noEmit
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -54,20 +53,20 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: openclaw/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd openclaw && pnpm install --frozen-lockfile
|
||||
run: cd integrations/openclaw && pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: cd openclaw && pnpm exec vitest run --coverage
|
||||
run: cd integrations/openclaw && pnpm exec vitest run --coverage
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
if: matrix.node-version == 20
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
flags: openclaw
|
||||
directory: openclaw/coverage
|
||||
directory: integrations/openclaw/coverage
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
@@ -86,15 +85,15 @@ jobs:
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: openclaw/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/openclaw/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd openclaw && pnpm install --frozen-lockfile
|
||||
run: cd integrations/openclaw && pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: cd openclaw && pnpm build
|
||||
run: cd integrations/openclaw && pnpm build
|
||||
|
||||
- name: Verify dist output exists
|
||||
run: |
|
||||
test -f openclaw/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
|
||||
test -f openclaw/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
|
||||
test -f integrations/openclaw/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
|
||||
test -f integrations/openclaw/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
name: Publish @mem0/opencode-plugin 📦 to npm
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged
|
||||
# opencode-v* is published. Can also be dispatched manually to re-publish
|
||||
# a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. opencode-v0.2.0)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Publish under the version preid dist-tag instead of latest'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish @mem0/opencode-plugin 📦 to npm
|
||||
if: startsWith(github.event.release.tag_name, 'opencode-v')
|
||||
if: startsWith(inputs.tag, 'opencode-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
defaults:
|
||||
run:
|
||||
working-directory: mem0-plugin/.opencode-plugin
|
||||
working-directory: integrations/mem0-plugin/.opencode-plugin
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
@@ -36,7 +50,7 @@ jobs:
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
|
||||
if [ "${{ inputs.prerelease }}" = "true" ]; then
|
||||
PREID=$(node -p "require('./package.json').version.split('-')[1].split('.')[0]")
|
||||
npx npm@latest publish --provenance --access public --tag "$PREID"
|
||||
else
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
name: opencode-plugin checks
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# push-to-main and manual runs remain standalone.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'mem0-plugin/.opencode-plugin/**'
|
||||
- '.github/workflows/opencode-plugin-checks.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'mem0-plugin/.opencode-plugin/**'
|
||||
- 'integrations/mem0-plugin/.opencode-plugin/**'
|
||||
- '.github/workflows/opencode-plugin-checks.yml'
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: mem0-plugin/.opencode-plugin
|
||||
working-directory: integrations/mem0-plugin/.opencode-plugin
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
name: Publish @mem0/pi-agent-plugin 📦 to npm
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged
|
||||
# pi-agent-v* is published. Can also be dispatched manually to re-publish
|
||||
# a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. pi-agent-v0.1.1)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Publish under the version preid dist-tag instead of latest'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish @mem0/pi-agent-plugin 📦 to npm
|
||||
if: startsWith(github.event.release.tag_name, 'pi-agent-v')
|
||||
if: startsWith(inputs.tag, 'pi-agent-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
defaults:
|
||||
run:
|
||||
working-directory: pi-agent-plugin
|
||||
working-directory: integrations/pi-agent-plugin
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
@@ -28,7 +42,7 @@ jobs:
|
||||
node-version: '22'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -38,7 +52,7 @@ jobs:
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
|
||||
if [ "${{ inputs.prerelease }}" = "true" ]; then
|
||||
PREID=$(node -p "require('./package.json').version.split('-')[1].split('.')[0]")
|
||||
npx npm@latest publish --provenance --access public --tag "$PREID"
|
||||
else
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
name: pi-agent-plugin checks
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# push-to-main and manual runs remain standalone.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'pi-agent-plugin/**'
|
||||
- '.github/workflows/pi-agent-plugin-checks.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'pi-agent-plugin/**'
|
||||
- 'integrations/pi-agent-plugin/**'
|
||||
- '.github/workflows/pi-agent-plugin-checks.yml'
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
@@ -28,13 +27,13 @@ jobs:
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd pi-agent-plugin && pnpm install --frozen-lockfile
|
||||
run: cd integrations/pi-agent-plugin && pnpm install --frozen-lockfile
|
||||
|
||||
- name: Type check
|
||||
run: cd pi-agent-plugin && pnpm exec tsc --noEmit
|
||||
run: cd integrations/pi-agent-plugin && pnpm exec tsc --noEmit
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -54,13 +53,13 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd pi-agent-plugin && pnpm install --frozen-lockfile
|
||||
run: cd integrations/pi-agent-plugin && pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run tests
|
||||
run: cd pi-agent-plugin && pnpm exec vitest run
|
||||
run: cd integrations/pi-agent-plugin && pnpm exec vitest run
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -77,17 +76,17 @@ jobs:
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: pi-agent-plugin/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/pi-agent-plugin/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd pi-agent-plugin && pnpm install --frozen-lockfile
|
||||
run: cd integrations/pi-agent-plugin && pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: cd pi-agent-plugin && pnpm build
|
||||
run: cd integrations/pi-agent-plugin && pnpm build
|
||||
|
||||
- name: Verify dist output exists
|
||||
run: |
|
||||
test -f pi-agent-plugin/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
|
||||
test -f pi-agent-plugin/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
|
||||
test -f pi-agent-plugin/dist/entry.js || (echo "Build output missing: dist/entry.js" && exit 1)
|
||||
test -f pi-agent-plugin/dist/entry.d.ts || (echo "Build output missing: dist/entry.d.ts" && exit 1)
|
||||
test -f integrations/pi-agent-plugin/dist/index.js || (echo "Build output missing: dist/index.js" && exit 1)
|
||||
test -f integrations/pi-agent-plugin/dist/index.d.ts || (echo "Build output missing: dist/index.d.ts" && exit 1)
|
||||
test -f integrations/pi-agent-plugin/dist/entry.js || (echo "Build output missing: dist/entry.js" && exit 1)
|
||||
test -f integrations/pi-agent-plugin/dist/entry.d.ts || (echo "Build output missing: dist/entry.d.ts" && exit 1)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
name: Release Router 🚦
|
||||
|
||||
# Single entry point for all release publishing.
|
||||
#
|
||||
# Package CD workflows no longer listen to release events themselves — this
|
||||
# router inspects the release tag and dispatches only the matching pipeline,
|
||||
# so each release produces one routed run instead of one real run plus seven
|
||||
# skipped ones.
|
||||
#
|
||||
# Re-publishing a release (e.g. after fixing registry settings) does NOT
|
||||
# require deleting and recreating it anymore — manually dispatch the
|
||||
# package's CD workflow from the tag instead:
|
||||
#
|
||||
# gh workflow run <package>-cd.yml --ref refs/tags/<tag> -f tag=<tag>
|
||||
#
|
||||
# Note: dispatching runs the workflow file as it exists at the given ref, so
|
||||
# this router can only dispatch tags created after the workflow_dispatch
|
||||
# conversion landed on main. For older tags, dispatch manually from main.
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
route:
|
||||
name: Route ${{ github.event.release.tag_name }} to its CD pipeline
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Match tag prefix to CD workflow
|
||||
id: match
|
||||
env:
|
||||
TAG: ${{ github.event.release.tag_name }}
|
||||
run: |
|
||||
# Specific package prefixes first; the bare v* (Python SDK) arm
|
||||
# must stay last so prefixed tags that also start with 'v'
|
||||
# (vercel-ai-v*) can never be routed to the Python pipeline.
|
||||
case "$TAG" in
|
||||
ts-v*) workflow="ts-sdk-cd.yml" ;;
|
||||
cli-node-v*) workflow="cli-node-cd.yml" ;;
|
||||
cli-v*) workflow="cli-python-cd.yml" ;;
|
||||
vercel-ai-v*) workflow="vercel-ai-cd.yml" ;;
|
||||
openclaw-v*) workflow="openclaw-cd.yml" ;;
|
||||
opencode-v*) workflow="opencode-plugin-cd.yml" ;;
|
||||
pi-agent-v*) workflow="pi-agent-plugin-cd.yml" ;;
|
||||
v*) workflow="cd.yml" ;;
|
||||
*)
|
||||
echo "::error::Release tag '$TAG' does not match any known package prefix — nothing will be published. See the tag prefix table in AGENTS.md."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
echo "workflow=$workflow" >> "$GITHUB_OUTPUT"
|
||||
echo ":outbox_tray: Routed \`$TAG\` → \`$workflow\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Dispatch ${{ steps.match.outputs.workflow }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAG: ${{ github.event.release.tag_name }}
|
||||
run: |
|
||||
# --ref points at the tag so the dispatched run builds (and signs
|
||||
# provenance for) the exact tagged commit.
|
||||
gh workflow run "${{ steps.match.outputs.workflow }}" \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--ref "refs/tags/$TAG" \
|
||||
-f tag="$TAG" \
|
||||
-f prerelease="${{ github.event.release.prerelease }}"
|
||||
@@ -1,13 +1,24 @@
|
||||
name: Publish mem0ai 📦 to npm
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged ts-v* is
|
||||
# published. Can also be dispatched manually to re-publish a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. ts-v2.1.0)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Publish under the version preid dist-tag instead of latest'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish mem0ai 📦 to npm
|
||||
if: startsWith(github.event.release.tag_name, 'ts-v')
|
||||
if: startsWith(inputs.tag, 'ts-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
@@ -16,6 +27,8 @@ jobs:
|
||||
working-directory: mem0-ts
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
@@ -38,7 +51,7 @@ jobs:
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
|
||||
if [ "${{ inputs.prerelease }}" = "true" ]; then
|
||||
PREID=$(node -p "require('./package.json').version.split('-')[1].split('.')[0]")
|
||||
npx npm@latest publish --provenance --access public --tag "$PREID"
|
||||
else
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
name: TypeScript SDK CI
|
||||
|
||||
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||
# push-to-main runs remain standalone.
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'mem0-ts/**'
|
||||
- '.github/workflows/ts-sdk-ci.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'mem0-ts/**'
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
check_changes:
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
name: Publish @mem0/vercel-ai-provider 📦 to npm
|
||||
|
||||
# Dispatched by release.yml (Release Router) when a release tagged
|
||||
# vercel-ai-v* is published. Can also be dispatched manually to re-publish
|
||||
# a tag.
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to build and publish (e.g. vercel-ai-v2.0.7)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Publish under the version preid dist-tag instead of latest'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish @mem0/vercel-ai-provider 📦 to npm
|
||||
if: startsWith(github.event.release.tag_name, 'vercel-ai-v')
|
||||
if: startsWith(inputs.tag, 'vercel-ai-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
defaults:
|
||||
run:
|
||||
working-directory: vercel-ai-sdk
|
||||
working-directory: integrations/vercel-ai-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.tag }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
@@ -28,7 +42,7 @@ jobs:
|
||||
node-version: '22'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: vercel-ai-sdk/pnpm-lock.yaml
|
||||
cache-dependency-path: integrations/vercel-ai-sdk/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -38,7 +52,7 @@ jobs:
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
|
||||
if [ "${{ inputs.prerelease }}" = "true" ]; then
|
||||
PREID=$(node -p "require('./package.json').version.split('-')[1].split('.')[0]")
|
||||
npx npm@latest publish --provenance --access public --tag "$PREID"
|
||||
else
|
||||
|
||||
@@ -22,11 +22,13 @@ This is a **polyglot monorepo** containing Python and TypeScript packages, CLIs,
|
||||
| `mem0-ts/` | TypeScript SDK (`mem0ai` on npm) — client + OSS memory |
|
||||
| `cli/python/` | Python CLI (`mem0-cli` on PyPI) — Typer-based, entry point `mem0` |
|
||||
| `cli/node/` | Node CLI (`@mem0/cli` on npm) — Commander-based, entry point `mem0` |
|
||||
| `vercel-ai-sdk/` | `@mem0/vercel-ai-provider` — Vercel AI SDK memory provider |
|
||||
| `openclaw/` | `@mem0/openclaw-mem0` — OpenClaw plugin for Claude Code / AI editors |
|
||||
| `integrations/` | **Agent & editor integrations**, one directory per integration (see "Adding a New Integration") |
|
||||
| `integrations/mem0-plugin/` | AI editor plugins (Claude Code, Cursor, Codex) — MCP server connection, lifecycle hooks, skills. Contains nested `.opencode-plugin/` (`@mem0/opencode-plugin`) |
|
||||
| `integrations/openclaw/` | `@mem0/openclaw-mem0` — OpenClaw plugin for Claude Code / AI editors |
|
||||
| `integrations/pi-agent-plugin/` | `@mem0/pi-agent-plugin` — Pi Agent plugin |
|
||||
| `integrations/vercel-ai-sdk/` | `@mem0/vercel-ai-provider` — Vercel AI SDK memory provider |
|
||||
| `server/` | FastAPI REST server for self-hosted Mem0 (Docker: FastAPI + PostgreSQL/pgvector + Neo4j) |
|
||||
| `openmemory/` | Self-hosted memory platform — `api/` (FastAPI + Alembic + MCP server) and `ui/` (Next.js 15 + React 19) |
|
||||
| `mem0-plugin/` | AI editor plugins (Claude Code, Cursor, Codex) — MCP server connection, lifecycle hooks, skills |
|
||||
| `skills/` | Claude Code skill definitions. Reference skills (SDK knowledge, always-on): `mem0/`, `mem0-cli/`, `mem0-vercel-ai-sdk/`. Pipeline skills (run on demand): `mem0-integrate/`, `mem0-test-integration/` |
|
||||
| `docs/` | Documentation site (Mintlify) |
|
||||
| `tests/` | Python SDK tests (pytest) |
|
||||
@@ -49,8 +51,8 @@ mem0 (Python SDK) mem0-ts (TypeScript SDK)
|
||||
|
||||
cli/python/ ──▶ mem0ai (optional, for OSS mode)
|
||||
cli/node/ ──▶ mem0ai (npm, for API calls)
|
||||
vercel-ai-sdk/ ──▶ ai, @ai-sdk/* providers
|
||||
openclaw/ ──▶ mem0ai (npm)
|
||||
integrations/vercel-ai-sdk/ ──▶ ai, @ai-sdk/* providers
|
||||
integrations/openclaw/ ──▶ mem0ai (npm)
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
@@ -73,8 +75,8 @@ pre-commit install # install git hooks
|
||||
# TypeScript packages
|
||||
cd mem0-ts && pnpm install # TS SDK
|
||||
cd cli/node && pnpm install # Node CLI
|
||||
cd vercel-ai-sdk && pnpm install # Vercel AI provider
|
||||
cd openclaw && pnpm install # OpenClaw plugin
|
||||
cd integrations/vercel-ai-sdk && pnpm install # Vercel AI provider
|
||||
cd integrations/openclaw && pnpm install # OpenClaw plugin
|
||||
```
|
||||
|
||||
## Build, Lint, and Test Commands
|
||||
@@ -162,10 +164,10 @@ pnpm run dev # tsx src/index.ts (development)
|
||||
- **Test:** vitest (not jest)
|
||||
- **Framework:** Commander + Chalk + ora + cli-table3
|
||||
|
||||
### Vercel AI SDK Provider (`vercel-ai-sdk/`)
|
||||
### Vercel AI SDK Provider (`integrations/vercel-ai-sdk/`)
|
||||
|
||||
```bash
|
||||
cd vercel-ai-sdk
|
||||
cd integrations/vercel-ai-sdk
|
||||
pnpm install
|
||||
pnpm run build # tsup
|
||||
pnpm run lint # eslint
|
||||
@@ -180,10 +182,10 @@ pnpm run test:node # vitest (node runtime)
|
||||
- **Lint:** ESLint + Prettier
|
||||
- **Test:** jest + vitest (edge/node configs)
|
||||
|
||||
### OpenClaw Plugin (`openclaw/`)
|
||||
### OpenClaw Plugin (`integrations/openclaw/`)
|
||||
|
||||
```bash
|
||||
cd openclaw
|
||||
cd integrations/openclaw
|
||||
pnpm install
|
||||
pnpm run build # tsup
|
||||
pnpm run test # vitest run
|
||||
@@ -342,8 +344,8 @@ make run-openai # OpenAI comparison
|
||||
|---------|--------|-----------|---------------|
|
||||
| `mem0-ts/` | — | Prettier | jest |
|
||||
| `cli/node/` | Biome | Biome | vitest |
|
||||
| `vercel-ai-sdk/` | ESLint | Prettier | jest + vitest |
|
||||
| `openclaw/` | — | — | vitest |
|
||||
| `integrations/vercel-ai-sdk/` | ESLint | Prettier | jest + vitest |
|
||||
| `integrations/openclaw/` | — | — | vitest |
|
||||
|
||||
### Type Checking
|
||||
|
||||
@@ -381,11 +383,11 @@ Model Context Protocol support in multiple places:
|
||||
|
||||
- **Remote:** MCP server at `mcp.mem0.ai`
|
||||
- **Local:** MCP server in `openmemory/api/` (FastAPI-based)
|
||||
- **Plugin:** MCP tools in `mem0-plugin/` — 9 tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`
|
||||
- **Plugin:** MCP tools in `integrations/mem0-plugin/` — 9 tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`
|
||||
|
||||
### Plugin & Skills System
|
||||
|
||||
- `mem0-plugin/` provides integrations for Claude Code, Cursor, and Codex via MCP server connections and lifecycle hooks for automatic memory capture.
|
||||
- `integrations/mem0-plugin/` provides integrations for Claude Code, Cursor, and Codex via MCP server connections and lifecycle hooks for automatic memory capture.
|
||||
- `skills/` contains structured skill definitions for AI agents, split into two categories:
|
||||
- **Reference skills** (always-on SDK knowledge): `mem0` (Python + TS SDKs, framework integrations), `mem0-cli` (terminal workflows), `mem0-vercel-ai-sdk` (Vercel AI provider).
|
||||
- **Pipeline skills** (run on demand): `mem0-integrate` wires Mem0 into an existing repo via a TDD pipeline; `mem0-test-integration` verifies what the integrator produced on the same branch. The two are loosely coupled via `.mem0-integration/` artifacts.
|
||||
@@ -402,24 +404,44 @@ To add a new LLM, embedding, vector store, or reranker provider:
|
||||
6. Add any new dependencies to the appropriate optional group in `pyproject.toml` (never to core `dependencies`)
|
||||
7. Follow the exact pattern of existing providers in the same category — match method signatures, error handling, and config structure
|
||||
|
||||
### Adding a New Integration
|
||||
|
||||
Agent/editor integrations live under `integrations/`. Each is a self-contained directory (its own `package.json`/lockfile, build, and tests). To add one:
|
||||
|
||||
1. Create `integrations/<name>/` and build the integration there.
|
||||
2. If it publishes to a registry, set `repository.directory: "integrations/<name>"` in its `package.json` so npm provenance links to the correct subdirectory.
|
||||
3. Add CI/CD under `.github/workflows/` (`<name>-checks.yml`, `<name>-cd.yml`). Use `integrations/<name>` in `paths:` triggers, `working-directory`, and `cache-dependency-path`. Register the release tag prefix in the `case` block in `release.yml` (keep the bare `v*` arm last). Keep workflow **filenames** stable — npm OIDC trusted publishing is pinned to repo + workflow filename.
|
||||
4. If it is a Claude Code / editor marketplace plugin, register its path in the five `marketplace.json` files (root + `.claude-plugin/`, `.cursor-plugin/`, `.codex-plugin/`, `.agents/plugins/`).
|
||||
5. Document it under `docs/integrations/` and add the page to `docs/docs.json` and `docs/llms.txt`.
|
||||
6. Add rows to the "Key Directories" table and the CI/CD tables in this file.
|
||||
|
||||
## CI/CD
|
||||
|
||||
### CI Workflows (automated testing)
|
||||
|
||||
| Workflow | File | Triggers | Tests |
|
||||
|----------|------|----------|-------|
|
||||
| Python SDK | `ci.yml` | Push to main, PRs on `mem0/`, `tests/`, `pyproject.toml` | Ruff lint + pytest on Python 3.10, 3.11, 3.12 |
|
||||
| TypeScript SDK | `ts-sdk-ci.yml` | Push to main, PRs on `mem0-ts/` | Prettier + build + jest on Node 20, 22 |
|
||||
| Python CLI | `cli-python-ci.yml` | Push to `cli/python/`, PRs, manual | Ruff lint + pytest + hatch build on Python 3.10, 3.11, 3.12 |
|
||||
| Node CLI | `cli-node-ci.yml` | Push to `cli/node/`, PRs, manual | Biome lint + tsc + vitest + tsup build on Node 20, 22 |
|
||||
| OpenClaw | `openclaw-checks.yml` | Push to `openclaw/`, PRs, manual | tsc + vitest (with Codecov) + tsup build on Node 20, 22 |
|
||||
| OpenCode Plugin | `opencode-plugin-checks.yml` | Push to `mem0-plugin/.opencode-plugin/`, PRs, manual | Bun: tsc type-check + build + dist artifact check |
|
||||
| Pi Agent Plugin | `pi-agent-plugin-checks.yml` | Push to `pi-agent-plugin/`, PRs, manual | tsc + vitest + tsup build (dist artifact check) on Node 20, 22 |
|
||||
PR testing is orchestrated by a single entry point: **`ci-gate.yml` (CI Gate)** runs on every PR, detects which packages changed, and invokes only the relevant package workflows below as reusable workflows (`workflow_call`). Its final **`CI Gate`** job aggregates the results (skipped pipelines pass; failed or cancelled ones fail) and is the **only status check that needs to be required** in branch protection. Package workflows keep their own push-to-main and manual triggers; their `pull_request` triggers moved into the gate's path filters.
|
||||
|
||||
| Workflow | File | Standalone Triggers | Tests |
|
||||
|----------|------|---------------------|-------|
|
||||
| CI Gate | `ci-gate.yml` | All PRs | Routes to and aggregates the workflows below |
|
||||
| Python SDK | `ci.yml` | Push to main | Ruff lint + pytest on Python 3.10, 3.11, 3.12 |
|
||||
| TypeScript SDK | `ts-sdk-ci.yml` | Push to main (on `mem0-ts/`) | Prettier + build + jest on Node 20, 22 |
|
||||
| Python CLI | `cli-python-ci.yml` | Push to main (on `cli/python/`), manual | Ruff lint + pytest + hatch build on Python 3.10, 3.11, 3.12 |
|
||||
| Node CLI | `cli-node-ci.yml` | Push to main (on `cli/node/`), manual | Biome lint + tsc + vitest + tsup build on Node 20, 22 |
|
||||
| OpenClaw | `openclaw-checks.yml` | Push to main (on `integrations/openclaw/`), manual | tsc + vitest (with Codecov) + tsup build on Node 20, 22 |
|
||||
| OpenCode Plugin | `opencode-plugin-checks.yml` | Push to main (on `integrations/mem0-plugin/.opencode-plugin/`), manual | Bun: tsc type-check + build + dist artifact check |
|
||||
| Pi Agent Plugin | `pi-agent-plugin-checks.yml` | Push to main (on `integrations/pi-agent-plugin/`), manual | tsc + vitest + tsup build (dist artifact check) on Node 20, 22 |
|
||||
| docs llms.txt | `docs-llms-txt-check.yml` | Manual | `docs/llms.txt` coverage check |
|
||||
|
||||
When adding a new package CI workflow: give it `workflow_call` (plus `push`/`workflow_dispatch` as needed, but no `pull_request` trigger), then register it in `ci-gate.yml` — a path filter under the `changes` job, a call job, and an entry in the gate job's `needs` list.
|
||||
|
||||
### CD Workflows (automated publishing)
|
||||
|
||||
Publishing is routed through a single entry point: **`release.yml` (Release Router)** is the only workflow that listens to `release: published` events. It matches the release tag prefix and dispatches the corresponding package workflow via `workflow_dispatch`, so each release produces exactly one routed run (no skipped runs from the other pipelines).
|
||||
|
||||
| Workflow | File | Tag Prefix | Target |
|
||||
|----------|------|------------|--------|
|
||||
| Release Router | `release.yml` | (all releases) | dispatches the matching workflow below |
|
||||
| Python SDK | `cd.yml` | `v*` | PyPI (`mem0ai`) |
|
||||
| TypeScript SDK | `ts-sdk-cd.yml` | `ts-v*` | npm (`mem0ai`) |
|
||||
| Python CLI | `cli-python-cd.yml` | `cli-v*` | PyPI (`mem0-cli`) |
|
||||
@@ -429,8 +451,11 @@ To add a new LLM, embedding, vector store, or reranker provider:
|
||||
| OpenCode Plugin | `opencode-plugin-cd.yml` | `opencode-v*` | npm (`@mem0/opencode-plugin`) |
|
||||
| Pi Agent Plugin | `pi-agent-plugin-cd.yml` | `pi-agent-v*` | npm (`@mem0/pi-agent-plugin`) |
|
||||
|
||||
- Package CD workflows are `workflow_dispatch`-only (inputs: `tag`, `prerelease`); they check out and build the given tag. Registry trusted-publisher settings stay pinned to each package's own workflow filename.
|
||||
- All publishing uses **OIDC trusted publishing** — no tokens or secrets required.
|
||||
- First publish of a new npm package must be done manually; OIDC works for subsequent versions.
|
||||
- To re-publish a release (e.g. after a registry settings fix), do **not** delete/recreate the GitHub release — manually dispatch the package workflow instead: `gh workflow run <package>-cd.yml --ref refs/tags/<tag> -f tag=<tag>`.
|
||||
- When adding a new package: add its CD workflow (`workflow_dispatch` with `tag`/`prerelease` inputs), then register its tag prefix in the `case` block in `release.yml`. Keep the bare `v*` arm last.
|
||||
|
||||
### Utility Workflows
|
||||
|
||||
|
||||
Generated
+17
-16
@@ -9,6 +9,7 @@ overrides:
|
||||
langsmith@<0.6.0: ^0.6.0
|
||||
tar-fs@>=2.0.0 <2.1.4: ^2.1.4
|
||||
picomatch@<2.3.2: ^2.3.2
|
||||
postcss@<8.5.10: '>=8.5.10'
|
||||
|
||||
importers:
|
||||
|
||||
@@ -38,7 +39,7 @@ importers:
|
||||
version: 20.19.37
|
||||
tsup:
|
||||
specifier: ^8.0.0
|
||||
version: 8.5.1(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)
|
||||
version: 8.5.1(postcss@8.5.15)(tsx@4.21.0)(typescript@5.9.3)
|
||||
tsx:
|
||||
specifier: ^4.7.0
|
||||
version: 4.21.0
|
||||
@@ -829,8 +830,8 @@ packages:
|
||||
mz@2.7.0:
|
||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
nanoid@3.3.12:
|
||||
resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
@@ -871,7 +872,7 @@ packages:
|
||||
engines: {node: '>= 18'}
|
||||
peerDependencies:
|
||||
jiti: '>=1.21.0'
|
||||
postcss: '>=8.0.9'
|
||||
postcss: '>=8.5.10'
|
||||
tsx: ^4.8.1
|
||||
yaml: ^2.4.2
|
||||
peerDependenciesMeta:
|
||||
@@ -884,8 +885,8 @@ packages:
|
||||
yaml:
|
||||
optional: true
|
||||
|
||||
postcss@8.5.8:
|
||||
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
||||
postcss@8.5.15:
|
||||
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
readdirp@4.1.2:
|
||||
@@ -997,7 +998,7 @@ packages:
|
||||
peerDependencies:
|
||||
'@microsoft/api-extractor': ^7.36.0
|
||||
'@swc/core': ^1
|
||||
postcss: ^8.4.12
|
||||
postcss: '>=8.5.10'
|
||||
typescript: '>=4.5.0'
|
||||
peerDependenciesMeta:
|
||||
'@microsoft/api-extractor':
|
||||
@@ -1671,7 +1672,7 @@ snapshots:
|
||||
object-assign: 4.1.1
|
||||
thenify-all: 1.6.0
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
nanoid@3.3.12: {}
|
||||
|
||||
object-assign@4.1.1: {}
|
||||
|
||||
@@ -1707,16 +1708,16 @@ snapshots:
|
||||
mlly: 1.8.2
|
||||
pathe: 2.0.3
|
||||
|
||||
postcss-load-config@6.0.1(postcss@8.5.8)(tsx@4.21.0):
|
||||
postcss-load-config@6.0.1(postcss@8.5.15)(tsx@4.21.0):
|
||||
dependencies:
|
||||
lilconfig: 3.1.3
|
||||
optionalDependencies:
|
||||
postcss: 8.5.8
|
||||
postcss: 8.5.15
|
||||
tsx: 4.21.0
|
||||
|
||||
postcss@8.5.8:
|
||||
postcss@8.5.15:
|
||||
dependencies:
|
||||
nanoid: 3.3.11
|
||||
nanoid: 3.3.12
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
@@ -1837,7 +1838,7 @@ snapshots:
|
||||
|
||||
ts-interface-checker@0.1.13: {}
|
||||
|
||||
tsup@8.5.1(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3):
|
||||
tsup@8.5.1(postcss@8.5.15)(tsx@4.21.0)(typescript@5.9.3):
|
||||
dependencies:
|
||||
bundle-require: 5.1.0(esbuild@0.27.4)
|
||||
cac: 6.7.14
|
||||
@@ -1848,7 +1849,7 @@ snapshots:
|
||||
fix-dts-default-cjs-exports: 1.0.1
|
||||
joycon: 3.1.1
|
||||
picocolors: 1.1.1
|
||||
postcss-load-config: 6.0.1(postcss@8.5.8)(tsx@4.21.0)
|
||||
postcss-load-config: 6.0.1(postcss@8.5.15)(tsx@4.21.0)
|
||||
resolve-from: 5.0.0
|
||||
rollup: 4.60.0
|
||||
source-map: 0.7.6
|
||||
@@ -1857,7 +1858,7 @@ snapshots:
|
||||
tinyglobby: 0.2.15
|
||||
tree-kill: 1.2.2
|
||||
optionalDependencies:
|
||||
postcss: 8.5.8
|
||||
postcss: 8.5.15
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
@@ -1885,7 +1886,7 @@ snapshots:
|
||||
esbuild: 0.25.12
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
picomatch: 4.0.4
|
||||
postcss: 8.5.8
|
||||
postcss: 8.5.15
|
||||
rollup: 4.60.0
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
|
||||
@@ -10,3 +10,4 @@ overrides:
|
||||
langsmith@<0.6.0: ^0.6.0
|
||||
tar-fs@>=2.0.0 <2.1.4: ^2.1.4
|
||||
picomatch@<2.3.2: ^2.3.2
|
||||
"postcss@<8.5.10": ">=8.5.10"
|
||||
|
||||
@@ -8,4 +8,10 @@ export default defineConfig({
|
||||
define: {
|
||||
__CLI_VERSION__: JSON.stringify(pkg.version),
|
||||
},
|
||||
test: {
|
||||
// Integration tests spawn the CLI via `npx tsx` (15s subprocess
|
||||
// timeout); the first spawn in a file pays a cold-start cost that can
|
||||
// exceed vitest's 5s default on CI runners.
|
||||
testTimeout: 30_000,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -8,8 +8,8 @@ from io import StringIO
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from click.exceptions import Exit as ClickExit
|
||||
from rich.console import Console
|
||||
from typer import Exit as TyperExit
|
||||
|
||||
from mem0_cli.commands.config_cmd import (
|
||||
cmd_config_get,
|
||||
@@ -181,7 +181,7 @@ class TestAddCommand:
|
||||
patch("mem0_cli.commands.memory.console", console),
|
||||
patch("mem0_cli.commands.memory.err_console", err_console),
|
||||
patch("mem0_cli.commands.memory._stdin_is_piped", return_value=False),
|
||||
pytest.raises((SystemExit, ClickExit)),
|
||||
pytest.raises((SystemExit, TyperExit)),
|
||||
):
|
||||
cmd_add(
|
||||
mock_backend,
|
||||
@@ -206,7 +206,7 @@ class TestAddCommand:
|
||||
with (
|
||||
patch("mem0_cli.commands.memory.console", console),
|
||||
patch("mem0_cli.commands.memory.err_console", err_console),
|
||||
pytest.raises((SystemExit, ClickExit)),
|
||||
pytest.raises((SystemExit, TyperExit)),
|
||||
):
|
||||
cmd_add(
|
||||
mock_backend,
|
||||
@@ -764,7 +764,7 @@ class TestImportCommand:
|
||||
with (
|
||||
patch("mem0_cli.commands.utils.console", console),
|
||||
patch("mem0_cli.commands.utils.err_console", err_console),
|
||||
pytest.raises((SystemExit, ClickExit)),
|
||||
pytest.raises((SystemExit, TyperExit)),
|
||||
):
|
||||
cmd_import(mock_backend, "/nonexistent/file.json", user_id=None, agent_id=None)
|
||||
|
||||
@@ -801,7 +801,7 @@ class TestEntitiesListCommand:
|
||||
with (
|
||||
patch("mem0_cli.commands.entities.console", console),
|
||||
patch("mem0_cli.commands.entities.err_console", err_console),
|
||||
pytest.raises((SystemExit, ClickExit)),
|
||||
pytest.raises((SystemExit, TyperExit)),
|
||||
):
|
||||
cmd_entities_list(mock_backend, "invalid", output="table")
|
||||
|
||||
@@ -944,7 +944,7 @@ class TestEntitiesDeleteCommand:
|
||||
with (
|
||||
patch("mem0_cli.commands.entities.console", console),
|
||||
patch("mem0_cli.commands.entities.err_console", err_console),
|
||||
pytest.raises((SystemExit, ClickExit)),
|
||||
pytest.raises((SystemExit, TyperExit)),
|
||||
):
|
||||
cmd_entities_delete(
|
||||
mock_backend,
|
||||
@@ -1308,7 +1308,7 @@ class TestAgentMode:
|
||||
patch("mem0_cli.commands.memory.console", console),
|
||||
patch("mem0_cli.commands.memory.err_console", err_console),
|
||||
patch("sys.stdout", captured_stdout),
|
||||
pytest.raises((SystemExit, ClickExit)),
|
||||
pytest.raises((SystemExit, TyperExit)),
|
||||
):
|
||||
cmd_get(mock_backend, "bad-id", output="text")
|
||||
|
||||
|
||||
@@ -7,6 +7,26 @@ mode: "wide"
|
||||
<Tabs>
|
||||
<Tab title="Python">
|
||||
|
||||
<Update label="2026-06-10" description="v2.0.5">
|
||||
|
||||
**New Features:**
|
||||
- **Memory:** Warn at init time when hybrid/BM25 search silently degrades to semantic-only because the configured vector store does not implement `keyword_search`. Affected stores: Chroma, FAISS, Cassandra, LangChain, Neptune Analytics, S3 Vectors, Supabase, TurboPuffer, Valkey ([#5444](https://github.com/mem0ai/mem0/pull/5444))
|
||||
- **Memory:** Add opt-in `explain=True` parameter to `Memory.search()` and `AsyncMemory.search()`. When enabled, each result includes a `score_breakdown` dict with `semantic`, `keyword` (normalized BM25), `entity_boost`, and `temporal_boost` signals so callers can understand and tune retrieval ranking ([#5102](https://github.com/mem0ai/mem0/pull/5102))
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Vector Stores:** Normalize similarity scores to `[0, 1]` (higher = better) consistently across all backends. 11 adapters previously returned raw distance metrics (lower = better) — FAISS, Chroma, Milvus, Redis, Cassandra, PGVector, S3 Vectors, Supabase, Valkey, Azure MySQL, and Vertex AI Vector Search — causing incorrect ranking in multi-store setups ([#5391](https://github.com/mem0ai/mem0/pull/5391))
|
||||
- **Memory:** Parallelize entity boost searches in `Memory.search()` and `AsyncMemory.search()`. Previously up to 8 entities were embedded and queried sequentially (16 serial round-trips with remote embedders); all entity lookups now run concurrently, eliminating multi-second latency on entity-rich queries ([#5377](https://github.com/mem0ai/mem0/pull/5377))
|
||||
- **Memory:** Reject empty or whitespace-only queries in `Memory.search()`, `AsyncMemory.search()`, `MemoryClient.search()`, and `AsyncMemoryClient.search()` before any embedding or API call is made. Also strips leading/trailing whitespace from valid queries ([#5258](https://github.com/mem0ai/mem0/pull/5258))
|
||||
- **LLMs:** Add `is_reasoning_model: Optional[bool]` override to `BaseLlmConfig` (surfaced on `OpenAILlmConfig` and `AzureOpenAILlmConfig`). Fixes silent zero-extraction when using Azure deployments with versioned `gpt-5.x` names that the automatic name-based heuristic cannot recognize ([#5327](https://github.com/mem0ai/mem0/pull/5327))
|
||||
- **LLMs:** Fix xAI LLM provider: add `XAIConfig` with `xai_base_url`, forward `tools`/`tool_choice` in `generate_response()`, and parse `tool_calls` in the response. Previously the provider raised `AttributeError` at init and silently dropped tool results ([#5190](https://github.com/mem0ai/mem0/pull/5190))
|
||||
- **Vector Stores:** Fix PGVector `ConnectionPool` hang in Docker Compose environments where the app container starts before Postgres is DNS-resolvable — switched to `open=False` to avoid blocking constructor or silent zombie pool ([#5155](https://github.com/mem0ai/mem0/pull/5155))
|
||||
- **Vector Stores:** Fix PGVector `sslmode` handling for PostgreSQL URIs — the `sslmode` query parameter is now correctly extracted and forwarded when building the async connection pool ([#5308](https://github.com/mem0ai/mem0/pull/5308))
|
||||
- **Vector Stores:** Fix S3 Vectors `list()` not applying metadata filters — filtering is now done client-side after fetching, with pagination preserved and `top_k` applied after filtering to prevent pre-truncation of matching rows ([#5018](https://github.com/mem0ai/mem0/pull/5018))
|
||||
- **Vector Stores:** Fix Upstash Vector `search()` routing all queries to the default namespace — `namespace` is now passed as a top-level keyword argument to `query_many()` instead of inside the per-query dict where it was silently ignored ([#5202](https://github.com/mem0ai/mem0/pull/5202))
|
||||
- **Core:** Replace mutable default arguments with `None` sentinels in embedder configs and the proxy module, preventing cross-request state contamination ([#5302](https://github.com/mem0ai/mem0/pull/5302))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-05-27" description="v2.0.4">
|
||||
|
||||
**New Features:**
|
||||
@@ -939,6 +959,20 @@ See the [OSS v1 to v2 migration guide](https://docs.mem0.ai/migration/oss-v1-to-
|
||||
</Tab>
|
||||
|
||||
<Tab title="TypeScript">
|
||||
|
||||
<Update label="2026-06-10" description="v3.0.7">
|
||||
|
||||
**New Features:**
|
||||
- **Embeddings:** Add `LMStudioEmbedding` provider for local embeddings via the LM Studio server ([#5377](https://github.com/mem0ai/mem0/pull/5377))
|
||||
- **Memory:** Add opt-in `explain: true` option to `Memory.search()`. When enabled, each result includes a `scoreBreakdown` object with `semantic`, `keyword`, `entityBoost`, and `temporalBoost` fields so callers can inspect and tune retrieval ranking ([#5102](https://github.com/mem0ai/mem0/pull/5102))
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Memory:** Parallelize entity boost searches in `Memory.search()`. All entity embed + store lookups now run concurrently instead of sequentially, eliminating multi-second latency on entity-rich queries with remote embedding providers ([#5377](https://github.com/mem0ai/mem0/pull/5377))
|
||||
- **Vector Stores:** Normalize similarity scores to `[0, 1]` (higher = better) — fixed score inversion in the Redis vector store adapter ([#5391](https://github.com/mem0ai/mem0/pull/5391))
|
||||
- **Embeddings:** Request `encoding_format: "float"` from the OpenAI embedder in both `embed()` and `embedBatch()`. Fixes incorrect vector dimensions when using OpenAI-compatible proxies that default to base64 encoding ([#5170](https://github.com/mem0ai/mem0/pull/5170))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-06-01" description="v3.0.6">
|
||||
|
||||
**Security:**
|
||||
|
||||
@@ -28,7 +28,7 @@ echo 'export MEM0_API_KEY="m0-your-api-key"' >> ~/.bashrc && source ~/.bashrc
|
||||
|
||||
```bash
|
||||
# Install the plugin (MCP server, hooks, scripts)
|
||||
npx degit mem0ai/mem0/mem0-plugin ~/.gemini/config/plugins/mem0
|
||||
npx degit mem0ai/mem0/integrations/mem0-plugin ~/.gemini/config/plugins/mem0
|
||||
```
|
||||
|
||||
This installs the MCP server, lifecycle hooks, and shared scripts.
|
||||
|
||||
@@ -43,7 +43,7 @@ bunx @mem0/opencode-plugin@latest install
|
||||
**Or let your agent do it** — paste this into OpenCode:
|
||||
|
||||
```
|
||||
Install @mem0/opencode-plugin by following https://raw.githubusercontent.com/mem0ai/mem0/main/mem0-plugin/.opencode-plugin/README.md
|
||||
Install @mem0/opencode-plugin by following https://raw.githubusercontent.com/mem0ai/mem0/main/integrations/mem0-plugin/.opencode-plugin/README.md
|
||||
```
|
||||
|
||||
All commands auto-add the plugin and MCP server to your `~/.config/opencode/opencode.json`. Restart OpenCode — you get the MCP server, lifecycle hooks, and all `/mem0:` slash commands.
|
||||
|
||||
@@ -59,6 +59,7 @@ For advanced settings, create `~/.pi/agent/mem0-config.json`:
|
||||
"userId": "your-username",
|
||||
"autoCapture": true,
|
||||
"defaultScope": "project",
|
||||
"searchThreshold": 0.3,
|
||||
"dream": {
|
||||
"enabled": true,
|
||||
"auto": true,
|
||||
@@ -75,12 +76,14 @@ For advanced settings, create `~/.pi/agent/mem0-config.json`:
|
||||
| `userId` | `string` | `$MEM0_USER_ID` or `"default"` | User identity for memory scoping |
|
||||
| `autoCapture` | `boolean` | `true` | Store facts from conversations automatically |
|
||||
| `defaultScope` | `string` | `"project"` | Default memory scope: `project`, `session`, or `global` |
|
||||
| `searchThreshold` | `number` | `0.3` | Minimum similarity score (0–1) a memory must reach to count as a match for `/mem0-search`, `/mem0-forget`, and `/mem0-pin`, enforced on each result's relevance score. Raise it to be stricter; lower it if relevant results are missed. |
|
||||
| `dream.enabled` | `boolean` | `true` | Enable dream consolidation |
|
||||
| `dream.auto` | `boolean` | `true` | Auto-trigger dreams when thresholds are met |
|
||||
| `dream.minHours` | `number` | `24` | Minimum hours between auto-dreams |
|
||||
| `dream.minSessions` | `number` | `5` | Minimum sessions before first auto-dream |
|
||||
| `dream.minMemories` | `number` | `20` | Minimum memories before auto-dream triggers |
|
||||
|
||||
|
||||
## What's Included
|
||||
|
||||
| Component | Description |
|
||||
|
||||
+2
-2
@@ -398,9 +398,9 @@ Each subdirectory is a Claude Code Skill (`SKILL.md` + supporting assets). Load
|
||||
|
||||
### Editor Plugin (shared glue)
|
||||
|
||||
Source: https://github.com/mem0ai/mem0/tree/main/mem0-plugin
|
||||
Source: https://github.com/mem0ai/mem0/tree/main/integrations/mem0-plugin
|
||||
|
||||
The `mem0-plugin/` directory provides MCP server connection, lifecycle hooks, and skill bundling for Claude Code, Cursor, Codex, OpenCode, and Antigravity. It exposes 9 MCP tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`.
|
||||
The `integrations/mem0-plugin/` directory provides MCP server connection, lifecycle hooks, and skill bundling for Claude Code, Cursor, Codex, OpenCode, and Antigravity. It exposes 9 MCP tools: `add_memory`, `search_memories`, `get_memories`, `get_memory`, `update_memory`, `delete_memory`, `delete_all_memories`, `delete_entities`, `list_entities`.
|
||||
|
||||
Editor-specific setup docs (already listed above under `## Integrations > AI Coding Tools`):
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ type RetrievedMemory = {
|
||||
|
||||
type NewMemory = {
|
||||
id: string;
|
||||
data: {
|
||||
data?: {
|
||||
memory: string;
|
||||
};
|
||||
event: "ADD" | "DELETE";
|
||||
event: "ADD" | "UPDATE" | "DELETE" | "GET";
|
||||
};
|
||||
|
||||
type NewMemoryAnnotation = {
|
||||
@@ -47,14 +47,16 @@ const useMemories = (): Memory[] => {
|
||||
() =>
|
||||
annotations?.filter(isMemoryAnnotation).flatMap((a) => {
|
||||
if (a.type === "mem0-update") {
|
||||
return a.memories.map(
|
||||
(m): Memory => ({
|
||||
event: m.event,
|
||||
id: m.id,
|
||||
memory: m.data.memory,
|
||||
score: 1,
|
||||
})
|
||||
);
|
||||
return a.memories
|
||||
.filter((m): m is NewMemory & { data: { memory: string } } => m.data != null)
|
||||
.map(
|
||||
(m): Memory => ({
|
||||
event: m.event,
|
||||
id: m.id,
|
||||
memory: m.data.memory,
|
||||
score: 1,
|
||||
})
|
||||
);
|
||||
} else if (a.type === "mem0-get") {
|
||||
return a.memories.map((m) => ({
|
||||
event: "GET",
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ opencode plugin @mem0/opencode-plugin
|
||||
**Or let your agent do it** — paste this into OpenCode:
|
||||
|
||||
```
|
||||
Install @mem0/opencode-plugin by following https://raw.githubusercontent.com/mem0ai/mem0/main/mem0-plugin/.opencode-plugin/README.md
|
||||
Install @mem0/opencode-plugin by following https://raw.githubusercontent.com/mem0ai/mem0/main/integrations/mem0-plugin/.opencode-plugin/README.md
|
||||
```
|
||||
|
||||
All commands auto-add the plugin and MCP server to your `~/.config/opencode/opencode.json`. No manual config needed.
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mem0ai/mem0",
|
||||
"directory": "mem0-plugin/.opencode-plugin"
|
||||
"directory": "integrations/mem0-plugin/.opencode-plugin"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -90,14 +90,14 @@ git clone https://github.com/mem0ai/mem0.git ~/codex-plugins/mem0-source
|
||||
codex plugin marketplace add ~/codex-plugins/mem0-source
|
||||
```
|
||||
|
||||
This points Codex at the repo's `.agents/plugins/marketplace.json`, which references `mem0-plugin/` as the local source. Restart Codex, run `/plugins`, and install **Mem0** from the **Mem0 Plugins** marketplace.
|
||||
This points Codex at the repo's `.agents/plugins/marketplace.json`, which references `integrations/mem0-plugin/` as the local source. Restart Codex, run `/plugins`, and install **Mem0** from the **Mem0 Plugins** marketplace.
|
||||
|
||||
> **Don't combine with Option A.** The plugin manifest auto-registers `mem0` as an MCP server via `mem0-plugin/.codex-mcp.json` — adding a manual `[mcp_servers.mem0]` block would duplicate the registration.
|
||||
> **Don't combine with Option A.** The plugin manifest auto-registers `mem0` as an MCP server via `integrations/mem0-plugin/.codex-mcp.json` — adding a manual `[mcp_servers.mem0]` block would duplicate the registration.
|
||||
|
||||
**Optional — enable lifecycle hooks.** Codex doesn't auto-wire hooks from plugin manifests; it only reads `~/.codex/hooks.json` (or `<repo>/.codex/hooks.json`) ([docs](https://developers.openai.com/codex/hooks)). Run the bundled installer once to merge Mem0's entries:
|
||||
|
||||
```bash
|
||||
python3 ~/codex-plugins/mem0-source/mem0-plugin/scripts/install_codex_hooks.py
|
||||
python3 ~/codex-plugins/mem0-source/integrations/mem0-plugin/scripts/install_codex_hooks.py
|
||||
```
|
||||
|
||||
This merges three entries into `~/.codex/hooks.json` with absolute paths pointing into your clone:
|
||||
@@ -190,7 +190,7 @@ See [OpenCode integration docs](https://docs.mem0.ai/integrations/opencode) for
|
||||
|
||||
```bash
|
||||
# Install the plugin (MCP server, hooks, scripts)
|
||||
npx degit mem0ai/mem0/mem0-plugin ~/.gemini/config/plugins/mem0
|
||||
npx degit mem0ai/mem0/integrations/mem0-plugin ~/.gemini/config/plugins/mem0
|
||||
```
|
||||
|
||||
This installs the MCP server, lifecycle hooks, and shared scripts.
|
||||
@@ -276,10 +276,10 @@ The background setup is idempotent and runs once per account (cached in `~/.mem0
|
||||
|
||||
```bash
|
||||
# Dry-run -- prints current vs proposed, no changes:
|
||||
python mem0-plugin/scripts/setup_coding_categories.py
|
||||
python integrations/mem0-plugin/scripts/setup_coding_categories.py
|
||||
|
||||
# Write explicitly:
|
||||
python mem0-plugin/scripts/setup_coding_categories.py --apply
|
||||
python integrations/mem0-plugin/scripts/setup_coding_categories.py --apply
|
||||
```
|
||||
|
||||
Requires the `mem0ai` Python SDK (`pip install mem0ai`) and `MEM0_API_KEY` set. `project.update(custom_categories=[...])` always replaces the full list.
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user