chore: merge origin/main into mintlify/af82bda4 and resolve conflicts

This commit is contained in:
mintlify[bot]
2026-09-16 11:46:52 +00:00
committed by GitHub
parent b5ae772eae
commit 08d9636491
693 changed files with 55668 additions and 22676 deletions
+47
View File
@@ -0,0 +1,47 @@
# Python CLI (`cli/python/`)
The `mem0-cli` package on PyPI. Typer-based, entry point `mem0`.
## Commands
```bash
pip install -e ".[dev]" # dev install: ruff + pytest
ruff check . # lint
ruff format . # format
pytest # test
hatch build # build
```
## Conventions
> **Line length is 100 here, not 120.** The root Python SDK uses 120. Running the root
> `make format` over this directory reformats every file and fails CI. Use the local
> `ruff` invocations above.
- **Python 3.10+.** Not 3.9, unlike the root SDK.
- **Ruff** with an extended rule set: `E`, `F`, `I`, `W`, `UP`, `B`, `SIM`, `RUF`.
Ignores `E501` (formatter handles it), `B008` (required by Typer's argument defaults),
and `SIM108`.
- **Ruff format:** double quotes, space indent, `docstring-code-format = true`.
- **isort** first-party is `mem0_cli` only.
- **pytest** for tests.
- Target version pinned to `py310`.
## Layout
```
cli/python/
├── src/mem0_cli/ package source (src layout)
└── tests/
```
Entry point: `mem0 = "mem0_cli.app:main"`.
## Dependencies
Typer + Rich + httpx. `mem0ai` is **optional**, exposed through the `[oss]` extra for OSS mode. Do not promote it to a required dependency.
## CI and release
- CI: `cli-python-ci.yml`, ruff + pytest + `hatch build` on Python 3.10, 3.11, 3.12.
- Release: tag prefix `cli-v*` dispatches `cli-python-cd.yml`, publishing to PyPI over OIDC.
+1
View File
@@ -0,0 +1 @@
AGENTS.md
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "mem0-cli"
version = "0.2.10"
version = "0.2.12"
description = "The official CLI for mem0 — the memory layer for AI agents"
readme = "README.md"
license = "Apache-2.0"
+1 -1
View File
@@ -1,3 +1,3 @@
"""mem0 CLI — the command-line interface for the mem0 memory layer."""
__version__ = "0.2.10"
__version__ = "0.2.12"
+29 -2
View File
@@ -278,6 +278,11 @@ def add(
custom_instructions: str | None = typer.Option(
None, "--custom-instructions", help="Custom instructions for fact extraction."
),
agent_custom_instructions: str | None = typer.Option(
None,
"--agent-custom-instructions",
help="Extraction instructions for agent-scoped memories, overriding the project setting.",
),
custom_categories: str | None = typer.Option(
None,
"--custom-categories",
@@ -327,6 +332,7 @@ def add(
expires=expires,
categories=categories,
custom_instructions=custom_instructions,
agent_custom_instructions=agent_custom_instructions,
custom_categories=custom_categories,
structured_data_schema=structured_data_schema,
timestamp=timestamp,
@@ -365,7 +371,11 @@ def search(
False, "--keyword", help="Use keyword search.", rich_help_panel="Search"
),
filter_json: str | None = typer.Option(
None, "--filter", help="Advanced filter expression (JSON).", rich_help_panel="Search"
None,
"--filter",
help='Advanced filter as JSON: {"AND": [...]} or {"OR": [...]}, '
'e.g. {"AND": [{"categories": {"in": ["work"]}}]}.',
rich_help_panel="Search",
),
fields: str | None = typer.Option(
None,
@@ -408,6 +418,7 @@ def search(
mem0 search "preferences" --user-id alice
mem0 search "tools" -u alice -o json -k 5
echo "preferences" | mem0 search -u alice
mem0 search "invoices" -u alice --filter '{"AND": [{"categories": {"in": ["work"]}}]}'
"""
from mem0_cli.commands.memory import cmd_search
@@ -1078,6 +1089,18 @@ def status(
)
@app.command(rich_help_panel="Management")
def version() -> None:
"""Show version and exit.
Example:
mem0 version
"""
from mem0_cli.commands.utils import cmd_version
cmd_version()
@app.command("import", rich_help_panel="Management")
def import_cmd(
file_path: str = typer.Argument(..., help="JSON file to import."),
@@ -1139,6 +1162,7 @@ def _build_help_json() -> dict:
"--expires": "Expiration date (YYYY-MM-DD).",
"--categories": "Not supported on add, use --custom-categories instead.",
"--custom-instructions": "Custom instructions for fact extraction.",
"--agent-custom-instructions": "Extraction instructions for agent-scoped memories, overriding the project setting.",
"--custom-categories": "Custom categories as a JSON array of {name: description} objects.",
"--structured-data-schema": "Schema for structured data extraction, as JSON.",
"--timestamp": "Unix timestamp for the memory.",
@@ -1158,7 +1182,10 @@ def _build_help_json() -> dict:
"--threshold": "Minimum similarity score (default: 0.3).",
"--rerank": "Enable reranking (Platform only).",
"--keyword": "Use keyword search instead of semantic.",
"--filter": "Advanced filter expression (JSON).",
"--filter": (
'Advanced filter as JSON: {"AND": [...]} or {"OR": [...]}, '
'e.g. {"AND": [{"categories": {"in": ["work"]}}]}.'
),
"--fields": "Specific fields to return (comma-separated).",
"--show-expired": "Include expired memories.",
"--reference-date": "Reference date for relative queries (YYYY-MM-DD or unix timestamp).",
+1
View File
@@ -26,6 +26,7 @@ class Backend(ABC):
infer: bool = True,
expires: str | None = None,
custom_instructions: str | None = None,
agent_custom_instructions: str | None = None,
custom_categories: list[dict] | None = None,
structured_data_schema: dict | None = None,
timestamp: int | None = None,
@@ -88,6 +88,7 @@ class PlatformBackend(Backend):
infer: bool = True,
expires: str | None = None,
custom_instructions: str | None = None,
agent_custom_instructions: str | None = None,
custom_categories: list[dict] | None = None,
structured_data_schema: dict | None = None,
timestamp: int | None = None,
@@ -117,6 +118,8 @@ class PlatformBackend(Backend):
payload["expiration_date"] = expires
if custom_instructions:
payload["custom_instructions"] = custom_instructions
if agent_custom_instructions:
payload["agent_custom_instructions"] = agent_custom_instructions
if custom_categories:
payload["custom_categories"] = custom_categories
if structured_data_schema:
@@ -77,6 +77,7 @@ def cmd_add(
expires: str | None,
categories: str | None,
custom_instructions: str | None = None,
agent_custom_instructions: str | None = None,
custom_categories: str | None = None,
structured_data_schema: str | None = None,
timestamp: int | None = None,
@@ -166,6 +167,7 @@ def cmd_add(
infer=not no_infer,
expires=expires,
custom_instructions=custom_instructions,
agent_custom_instructions=agent_custom_instructions,
custom_categories=custom_cats,
structured_data_schema=schema,
timestamp=timestamp,
+12 -1
View File
@@ -91,7 +91,12 @@ class TestCLIIntegration:
flag = _run(["--version"])
assert flag.returncode == 0
assert __version__ in flag.stdout
assert _run(["version"]).returncode != 0
def test_version_subcommand_matches_flag_byte_for_byte(self):
flag = _run(["--version"])
cmd = _run(["version"])
assert cmd.returncode == 0
assert cmd.stdout == flag.stdout
@pytest.mark.parametrize(
"args",
@@ -127,6 +132,12 @@ class TestCLIIntegration:
assert result.returncode == 0
assert "top-k" in result.stdout
def test_search_help_documents_filter_json_shape(self):
result = _run(["search", "--help"])
assert result.returncode == 0
assert "AND" in result.stdout
assert "categories" in result.stdout
def test_list_help(self):
result = _run(["list", "--help"])
assert result.returncode == 0
+1
View File
@@ -38,6 +38,7 @@ ADD_MAPPING: dict[str, list[str]] = {
"metadata": ["metadata"],
"expiration_date": ["expires"],
"custom_instructions": ["custom_instructions"],
"agent_custom_instructions": ["agent_custom_instructions"],
"custom_categories": ["custom_categories"],
"infer": ["no_infer"],
"immutable": ["immutable"],
@@ -22,12 +22,14 @@ class TestAddOptions:
metadata={"source": "test"},
expires="2099-01-01",
custom_instructions="Extract only preferences.",
agent_custom_instructions="Extract only tool outcomes.",
custom_categories=[{"prefs": "user preferences"}],
structured_data_schema={"type": "object"},
timestamp=1700000000,
)
payload = mock_request.call_args.kwargs["json"]
assert payload["custom_instructions"] == "Extract only preferences."
assert payload["agent_custom_instructions"] == "Extract only tool outcomes."
assert payload["custom_categories"] == [{"prefs": "user preferences"}]
assert payload["structured_data_schema"] == {"type": "object"}
assert payload["timestamp"] == 1700000000
@@ -40,6 +42,7 @@ class TestAddOptions:
backend.add(content="hello", user_id="alice")
payload = mock_request.call_args.kwargs["json"]
assert "custom_instructions" not in payload
assert "agent_custom_instructions" not in payload
assert "custom_categories" not in payload
assert "structured_data_schema" not in payload
assert "timestamp" not in payload