mem0-cli 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mem0_cli-0.2.0/.gitignore +188 -0
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/PKG-INFO +18 -1
- mem0_cli-0.2.0/README.md +46 -0
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/pyproject.toml +1 -1
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/app.py +177 -26
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/backend/base.py +5 -0
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/backend/platform.py +22 -23
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/branding.py +50 -4
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/commands/config_cmd.py +33 -9
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/commands/entities.py +62 -27
- mem0_cli-0.2.0/src/mem0_cli/commands/events_cmd.py +176 -0
- mem0_cli-0.2.0/src/mem0_cli/commands/init_cmd.py +394 -0
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/commands/memory.py +229 -21
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/commands/utils.py +30 -10
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/config.py +14 -1
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/output.py +126 -9
- mem0_cli-0.2.0/src/mem0_cli/state.py +24 -0
- mem0_cli-0.1.0/.gitignore +0 -2
- mem0_cli-0.1.0/README.md +0 -29
- mem0_cli-0.1.0/src/mem0_cli/commands/init_cmd.py +0 -195
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/__init__.py +0 -0
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/__main__.py +0 -0
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/backend/__init__.py +0 -0
- {mem0_cli-0.1.0 → mem0_cli-0.2.0}/src/mem0_cli/commands/__init__.py +0 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
**/node_modules/
|
|
6
|
+
|
|
7
|
+
# C extensions
|
|
8
|
+
*.so
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
.Python
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py,cover
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended not to include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
110
|
+
.pdm.toml
|
|
111
|
+
|
|
112
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
113
|
+
__pypackages__/
|
|
114
|
+
|
|
115
|
+
# Celery stuff
|
|
116
|
+
celerybeat-schedule
|
|
117
|
+
celerybeat.pid
|
|
118
|
+
|
|
119
|
+
# SageMath parsed files
|
|
120
|
+
*.sage.py
|
|
121
|
+
|
|
122
|
+
# Environments
|
|
123
|
+
.env
|
|
124
|
+
.venv
|
|
125
|
+
env/
|
|
126
|
+
venv/
|
|
127
|
+
ENV/
|
|
128
|
+
env.bak/
|
|
129
|
+
venv.bak/
|
|
130
|
+
pyenv/
|
|
131
|
+
|
|
132
|
+
# Spyder project settings
|
|
133
|
+
.spyderproject
|
|
134
|
+
.spyproject
|
|
135
|
+
|
|
136
|
+
# Rope project settings
|
|
137
|
+
.ropeproject
|
|
138
|
+
|
|
139
|
+
# mkdocs documentation
|
|
140
|
+
/site
|
|
141
|
+
|
|
142
|
+
# mypy
|
|
143
|
+
.mypy_cache/
|
|
144
|
+
.dmypy.json
|
|
145
|
+
dmypy.json
|
|
146
|
+
|
|
147
|
+
# Pyre type checker
|
|
148
|
+
.pyre/
|
|
149
|
+
|
|
150
|
+
# pytype static type analyzer
|
|
151
|
+
.pytype/
|
|
152
|
+
|
|
153
|
+
# Cython debug symbols
|
|
154
|
+
cython_debug/
|
|
155
|
+
|
|
156
|
+
# PyCharm
|
|
157
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
158
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
159
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
160
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
161
|
+
#.idea/
|
|
162
|
+
|
|
163
|
+
.ideas.md
|
|
164
|
+
.todos.md
|
|
165
|
+
|
|
166
|
+
# Database
|
|
167
|
+
db
|
|
168
|
+
test-db
|
|
169
|
+
!embedchain/embedchain/core/db/
|
|
170
|
+
|
|
171
|
+
.vscode
|
|
172
|
+
.idea/
|
|
173
|
+
|
|
174
|
+
.DS_Store
|
|
175
|
+
|
|
176
|
+
notebooks/*.yaml
|
|
177
|
+
.ipynb_checkpoints/
|
|
178
|
+
|
|
179
|
+
!configs/*.yaml
|
|
180
|
+
|
|
181
|
+
# cache db
|
|
182
|
+
*.db
|
|
183
|
+
|
|
184
|
+
# local directories for testing
|
|
185
|
+
eval/
|
|
186
|
+
qdrant_storage/
|
|
187
|
+
.crossnote
|
|
188
|
+
testing.ipynb
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mem0-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: The official CLI for mem0 — the memory layer for AI agents
|
|
5
5
|
Author-email: "mem0.ai" <founders@mem0.ai>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -32,10 +32,20 @@ The official command-line interface for [mem0](https://mem0.ai) — the memory l
|
|
|
32
32
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
35
|
+
### Using pipx (recommended)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pipx install mem0-cli
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Using pip
|
|
42
|
+
|
|
35
43
|
```bash
|
|
36
44
|
pip install mem0-cli
|
|
37
45
|
```
|
|
38
46
|
|
|
47
|
+
> **Note:** On macOS with Homebrew Python, `pip install` outside a virtual environment will fail with an `externally-managed-environment` error ([PEP 668](https://peps.python.org/pep-0668/)). Use `pipx` instead, or install inside a virtual environment.
|
|
48
|
+
|
|
39
49
|
## Quick Start
|
|
40
50
|
|
|
41
51
|
```bash
|
|
@@ -52,6 +62,13 @@ mem0 search "What are Alice's preferences?" --user-id alice
|
|
|
52
62
|
mem0 list --user-id alice
|
|
53
63
|
```
|
|
54
64
|
|
|
65
|
+
## Releasing
|
|
66
|
+
|
|
67
|
+
1. Update `version` in `pyproject.toml`
|
|
68
|
+
2. Create a GitHub Release with tag `cli-v<version>` (e.g. `cli-v0.2.0`)
|
|
69
|
+
|
|
70
|
+
For a pre-release, use a beta version like `0.2.0b1` and check the **pre-release** checkbox.
|
|
71
|
+
|
|
55
72
|
## License
|
|
56
73
|
|
|
57
74
|
Apache-2.0
|
mem0_cli-0.2.0/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# mem0 CLI
|
|
2
|
+
|
|
3
|
+
The official command-line interface for [mem0](https://mem0.ai) — the memory layer for AI agents.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Using pipx (recommended)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pipx install mem0-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Using pip
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install mem0-cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
> **Note:** On macOS with Homebrew Python, `pip install` outside a virtual environment will fail with an `externally-managed-environment` error ([PEP 668](https://peps.python.org/pep-0668/)). Use `pipx` instead, or install inside a virtual environment.
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Set up your configuration
|
|
25
|
+
mem0 init
|
|
26
|
+
|
|
27
|
+
# Add a memory
|
|
28
|
+
mem0 add "I prefer dark mode and use vim keybindings" --user-id alice
|
|
29
|
+
|
|
30
|
+
# Search memories
|
|
31
|
+
mem0 search "What are Alice's preferences?" --user-id alice
|
|
32
|
+
|
|
33
|
+
# List all memories
|
|
34
|
+
mem0 list --user-id alice
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Releasing
|
|
38
|
+
|
|
39
|
+
1. Update `version` in `pyproject.toml`
|
|
40
|
+
2. Create a GitHub Release with tag `cli-v<version>` (e.g. `cli-v0.2.0`)
|
|
41
|
+
|
|
42
|
+
For a pre-release, use a beta version like `0.2.0b1` and check the **pre-release** checkbox.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
Apache-2.0
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import json as _json
|
|
6
|
+
import os
|
|
7
|
+
import stat as _stat_mod
|
|
6
8
|
import sys
|
|
7
9
|
from pathlib import Path
|
|
8
10
|
|
|
@@ -43,7 +45,14 @@ entity_app = typer.Typer(
|
|
|
43
45
|
no_args_is_help=True,
|
|
44
46
|
rich_markup_mode="rich",
|
|
45
47
|
)
|
|
46
|
-
|
|
48
|
+
|
|
49
|
+
event_app = typer.Typer(
|
|
50
|
+
name="event",
|
|
51
|
+
help="Inspect background processing events.",
|
|
52
|
+
no_args_is_help=True,
|
|
53
|
+
rich_markup_mode="rich",
|
|
54
|
+
)
|
|
55
|
+
# entity_app and event_app registered after Memory commands to control panel ordering
|
|
47
56
|
|
|
48
57
|
|
|
49
58
|
# ── Helpers ───────────────────────────────────────────────────────────────
|
|
@@ -114,9 +123,22 @@ def _resolve_ids(
|
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
|
|
126
|
+
def _stdin_is_piped() -> bool:
|
|
127
|
+
"""Return True only when stdin is an actual pipe or file redirect — not a bare open fd."""
|
|
128
|
+
from mem0_cli.state import is_agent_mode
|
|
129
|
+
|
|
130
|
+
if is_agent_mode():
|
|
131
|
+
return False
|
|
132
|
+
try:
|
|
133
|
+
mode = os.fstat(sys.stdin.fileno()).st_mode
|
|
134
|
+
return _stat_mod.S_ISFIFO(mode) or _stat_mod.S_ISREG(mode)
|
|
135
|
+
except Exception:
|
|
136
|
+
return False
|
|
137
|
+
|
|
138
|
+
|
|
117
139
|
def _read_stdin() -> str | None:
|
|
118
|
-
"""Read from stdin if it is
|
|
119
|
-
if
|
|
140
|
+
"""Read from stdin if it is an actual pipe or file redirect (not a TTY, not agent mode)."""
|
|
141
|
+
if _stdin_is_piped():
|
|
120
142
|
return sys.stdin.read().strip() or None
|
|
121
143
|
return None
|
|
122
144
|
|
|
@@ -128,7 +150,18 @@ def _read_stdin() -> str | None:
|
|
|
128
150
|
def main_callback(
|
|
129
151
|
ctx: typer.Context,
|
|
130
152
|
version: bool = typer.Option(False, "--version", help="Show version and exit."),
|
|
153
|
+
json_agent: bool = typer.Option(
|
|
154
|
+
False,
|
|
155
|
+
"--json",
|
|
156
|
+
"--agent",
|
|
157
|
+
help="Output as JSON for agent/programmatic use.",
|
|
158
|
+
is_eager=False,
|
|
159
|
+
),
|
|
131
160
|
) -> None:
|
|
161
|
+
if json_agent:
|
|
162
|
+
from mem0_cli.state import set_agent_mode
|
|
163
|
+
|
|
164
|
+
set_agent_mode(True)
|
|
132
165
|
if version:
|
|
133
166
|
from mem0_cli.commands.utils import cmd_version
|
|
134
167
|
|
|
@@ -253,8 +286,12 @@ def search(
|
|
|
253
286
|
help="Specific fields to return (comma-separated).",
|
|
254
287
|
rich_help_panel="Search",
|
|
255
288
|
),
|
|
256
|
-
graph: bool = typer.Option(
|
|
257
|
-
|
|
289
|
+
graph: bool = typer.Option(
|
|
290
|
+
False, "--graph", help="Enable graph in search.", rich_help_panel="Search"
|
|
291
|
+
),
|
|
292
|
+
no_graph: bool = typer.Option(
|
|
293
|
+
False, "--no-graph", help="Disable graph in search.", rich_help_panel="Search"
|
|
294
|
+
),
|
|
258
295
|
output: str = typer.Option(
|
|
259
296
|
"text", "--output", "-o", help="Output: text, json, table.", rich_help_panel="Output"
|
|
260
297
|
),
|
|
@@ -269,7 +306,7 @@ def search(
|
|
|
269
306
|
None, "--base-url", help="Override API base URL.", rich_help_panel="Connection"
|
|
270
307
|
),
|
|
271
308
|
) -> None:
|
|
272
|
-
"""
|
|
309
|
+
"""Query your memory store — semantic, keyword, or hybrid retrieval.
|
|
273
310
|
|
|
274
311
|
Examples:
|
|
275
312
|
mem0 search "preferences" --user-id alice
|
|
@@ -281,8 +318,8 @@ def search(
|
|
|
281
318
|
# STEP 7: stdin fallback for query
|
|
282
319
|
if query is None:
|
|
283
320
|
query = _read_stdin()
|
|
284
|
-
if query
|
|
285
|
-
print_error(err_console, "
|
|
321
|
+
if not query or not query.strip():
|
|
322
|
+
print_error(err_console, "Search query cannot be empty.")
|
|
286
323
|
raise typer.Exit(1)
|
|
287
324
|
|
|
288
325
|
backend, config = _get_backend_and_config(api_key, base_url)
|
|
@@ -372,8 +409,12 @@ def list_cmd(
|
|
|
372
409
|
before: str | None = typer.Option(
|
|
373
410
|
None, "--before", help="Created before (YYYY-MM-DD).", rich_help_panel="Filters"
|
|
374
411
|
),
|
|
375
|
-
graph: bool = typer.Option(
|
|
376
|
-
|
|
412
|
+
graph: bool = typer.Option(
|
|
413
|
+
False, "--graph", help="Enable graph in listing.", rich_help_panel="Filters"
|
|
414
|
+
),
|
|
415
|
+
no_graph: bool = typer.Option(
|
|
416
|
+
False, "--no-graph", help="Disable graph in listing.", rich_help_panel="Filters"
|
|
417
|
+
),
|
|
377
418
|
output: str = typer.Option(
|
|
378
419
|
"table", "--output", "-o", help="Output: text, json, table.", rich_help_panel="Output"
|
|
379
420
|
),
|
|
@@ -463,11 +504,19 @@ def update(
|
|
|
463
504
|
|
|
464
505
|
@app.command(rich_help_panel="Memory")
|
|
465
506
|
def delete(
|
|
466
|
-
memory_id: str | None = typer.Argument(
|
|
507
|
+
memory_id: str | None = typer.Argument(
|
|
508
|
+
None, help="Memory ID to delete (omit when using --all or --entity)."
|
|
509
|
+
),
|
|
467
510
|
all_: bool = typer.Option(False, "--all", help="Delete all memories matching scope filters."),
|
|
468
|
-
entity: bool = typer.Option(
|
|
469
|
-
|
|
470
|
-
|
|
511
|
+
entity: bool = typer.Option(
|
|
512
|
+
False, "--entity", help="Delete the entity itself and all its memories (cascade)."
|
|
513
|
+
),
|
|
514
|
+
project: bool = typer.Option(
|
|
515
|
+
False, "--project", help="With --all: delete ALL memories project-wide."
|
|
516
|
+
),
|
|
517
|
+
dry_run: bool = typer.Option(
|
|
518
|
+
False, "--dry-run", help="Show what would be deleted without deleting."
|
|
519
|
+
),
|
|
471
520
|
force: bool = typer.Option(False, "--force", help="Skip confirmation."),
|
|
472
521
|
user_id: str | None = typer.Option(
|
|
473
522
|
None, "--user-id", "-u", help="Scope to user.", rich_help_panel="Scope"
|
|
@@ -641,14 +690,12 @@ def entity_delete(
|
|
|
641
690
|
agent_id: str | None = typer.Option(
|
|
642
691
|
None, "--agent-id", help="Agent ID.", rich_help_panel="Scope"
|
|
643
692
|
),
|
|
644
|
-
app_id: str | None = typer.Option(
|
|
645
|
-
|
|
646
|
-
),
|
|
647
|
-
run_id: str | None = typer.Option(
|
|
648
|
-
None, "--run-id", help="Run ID.", rich_help_panel="Scope"
|
|
649
|
-
),
|
|
693
|
+
app_id: str | None = typer.Option(None, "--app-id", help="App ID.", rich_help_panel="Scope"),
|
|
694
|
+
run_id: str | None = typer.Option(None, "--run-id", help="Run ID.", rich_help_panel="Scope"),
|
|
650
695
|
force: bool = typer.Option(False, "--force", help="Skip confirmation."),
|
|
651
|
-
dry_run: bool = typer.Option(
|
|
696
|
+
dry_run: bool = typer.Option(
|
|
697
|
+
False, "--dry-run", help="Show what would be deleted without deleting."
|
|
698
|
+
),
|
|
652
699
|
output: str = typer.Option(
|
|
653
700
|
"text", "--output", "-o", help="Output: text, json, quiet.", rich_help_panel="Output"
|
|
654
701
|
),
|
|
@@ -688,23 +735,98 @@ def entity_delete(
|
|
|
688
735
|
app.add_typer(entity_app, name="entity", rich_help_panel="Management")
|
|
689
736
|
|
|
690
737
|
|
|
738
|
+
# ── Event subcommands ─────────────────────────────────────────────────────
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
@event_app.command("list")
|
|
742
|
+
def event_list(
|
|
743
|
+
output: str = typer.Option(
|
|
744
|
+
"table", "--output", "-o", help="Output: table, json.", rich_help_panel="Output"
|
|
745
|
+
),
|
|
746
|
+
api_key: str | None = typer.Option(
|
|
747
|
+
None,
|
|
748
|
+
"--api-key",
|
|
749
|
+
help="Override API key.",
|
|
750
|
+
envvar="MEM0_API_KEY",
|
|
751
|
+
rich_help_panel="Connection",
|
|
752
|
+
),
|
|
753
|
+
base_url: str | None = typer.Option(
|
|
754
|
+
None, "--base-url", help="Override API base URL.", rich_help_panel="Connection"
|
|
755
|
+
),
|
|
756
|
+
) -> None:
|
|
757
|
+
"""List recent background processing events.
|
|
758
|
+
|
|
759
|
+
Examples:
|
|
760
|
+
mem0 event list
|
|
761
|
+
mem0 event list -o json
|
|
762
|
+
"""
|
|
763
|
+
from mem0_cli.commands.events_cmd import cmd_event_list
|
|
764
|
+
|
|
765
|
+
backend = _get_backend(api_key, base_url)
|
|
766
|
+
cmd_event_list(backend, output=output)
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
@event_app.command("status")
|
|
770
|
+
def event_status(
|
|
771
|
+
event_id: str = typer.Argument(..., help="Event ID to inspect."),
|
|
772
|
+
output: str = typer.Option(
|
|
773
|
+
"text", "--output", "-o", help="Output: text, json.", rich_help_panel="Output"
|
|
774
|
+
),
|
|
775
|
+
api_key: str | None = typer.Option(
|
|
776
|
+
None,
|
|
777
|
+
"--api-key",
|
|
778
|
+
help="Override API key.",
|
|
779
|
+
envvar="MEM0_API_KEY",
|
|
780
|
+
rich_help_panel="Connection",
|
|
781
|
+
),
|
|
782
|
+
base_url: str | None = typer.Option(
|
|
783
|
+
None, "--base-url", help="Override API base URL.", rich_help_panel="Connection"
|
|
784
|
+
),
|
|
785
|
+
) -> None:
|
|
786
|
+
"""Check the status of a specific background event.
|
|
787
|
+
|
|
788
|
+
Examples:
|
|
789
|
+
mem0 event status <event-id>
|
|
790
|
+
mem0 event status <event-id> -o json
|
|
791
|
+
"""
|
|
792
|
+
from mem0_cli.commands.events_cmd import cmd_event_status
|
|
793
|
+
|
|
794
|
+
backend = _get_backend(api_key, base_url)
|
|
795
|
+
cmd_event_status(backend, event_id, output=output)
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
# ── Event subgroup ──
|
|
799
|
+
app.add_typer(event_app, name="event", rich_help_panel="Management")
|
|
800
|
+
|
|
801
|
+
|
|
691
802
|
# ── Management commands ───────────────────────────────────────────────────
|
|
692
803
|
|
|
693
804
|
|
|
694
805
|
@app.command(rich_help_panel="Management")
|
|
695
806
|
def init(
|
|
696
807
|
api_key: str | None = typer.Option(None, "--api-key", help="API key (skip prompt)."),
|
|
697
|
-
user_id: str | None = typer.Option(
|
|
808
|
+
user_id: str | None = typer.Option(
|
|
809
|
+
None, "--user-id", "-u", help="Default user ID (skip prompt)."
|
|
810
|
+
),
|
|
811
|
+
email: str | None = typer.Option(None, "--email", help="Login via email verification code."),
|
|
812
|
+
code: str | None = typer.Option(
|
|
813
|
+
None, "--code", help="Verification code (use with --email for non-interactive login)."
|
|
814
|
+
),
|
|
815
|
+
force: bool = typer.Option(
|
|
816
|
+
False, "--force", help="Overwrite existing config without confirmation."
|
|
817
|
+
),
|
|
698
818
|
) -> None:
|
|
699
819
|
"""Interactive setup wizard for mem0 CLI.
|
|
700
820
|
|
|
701
821
|
Examples:
|
|
702
822
|
mem0 init
|
|
703
823
|
mem0 init --api-key m0-xxx --user-id alice
|
|
824
|
+
mem0 init --email alice@company.com
|
|
825
|
+
mem0 init --email alice@company.com --code 482901
|
|
704
826
|
"""
|
|
705
827
|
from mem0_cli.commands.init_cmd import run_init
|
|
706
828
|
|
|
707
|
-
run_init(api_key=api_key, user_id=user_id)
|
|
829
|
+
run_init(api_key=api_key, user_id=user_id, email=email, code=code, force=force)
|
|
708
830
|
|
|
709
831
|
|
|
710
832
|
# (entity_app registered at module level, below sub-group definitions)
|
|
@@ -743,7 +865,6 @@ def status(
|
|
|
743
865
|
)
|
|
744
866
|
|
|
745
867
|
|
|
746
|
-
|
|
747
868
|
@app.command("import", rich_help_panel="Management")
|
|
748
869
|
def import_cmd(
|
|
749
870
|
file_path: str = typer.Argument(..., help="JSON file to import."),
|
|
@@ -810,7 +931,7 @@ def _build_help_json() -> dict:
|
|
|
810
931
|
},
|
|
811
932
|
},
|
|
812
933
|
"search": {
|
|
813
|
-
"description": "
|
|
934
|
+
"description": "Query your memory store — semantic, keyword, or hybrid retrieval.",
|
|
814
935
|
"usage": "mem0 search <query> [OPTIONS]",
|
|
815
936
|
"arguments": {"query": {"description": "Search query.", "required": False}},
|
|
816
937
|
"options": {
|
|
@@ -914,6 +1035,24 @@ def _build_help_json() -> dict:
|
|
|
914
1035
|
"value": {"description": "Value to set.", "required": True},
|
|
915
1036
|
},
|
|
916
1037
|
},
|
|
1038
|
+
"event": {
|
|
1039
|
+
"description": "Inspect background processing events.",
|
|
1040
|
+
"subcommands": {
|
|
1041
|
+
"list": {
|
|
1042
|
+
"description": "List recent background processing events.",
|
|
1043
|
+
"usage": "mem0 event list [OPTIONS]",
|
|
1044
|
+
"options": {"--output, -o": "Output format: table, json."},
|
|
1045
|
+
},
|
|
1046
|
+
"status": {
|
|
1047
|
+
"description": "Check the status of a specific background event.",
|
|
1048
|
+
"usage": "mem0 event status <event_id> [OPTIONS]",
|
|
1049
|
+
"arguments": {
|
|
1050
|
+
"event_id": {"description": "Event ID to inspect.", "required": True}
|
|
1051
|
+
},
|
|
1052
|
+
"options": {"--output, -o": "Output format: text, json."},
|
|
1053
|
+
},
|
|
1054
|
+
},
|
|
1055
|
+
},
|
|
917
1056
|
"entity": {
|
|
918
1057
|
"description": "Manage entities.",
|
|
919
1058
|
"subcommands": {
|
|
@@ -965,6 +1104,7 @@ def _build_help_json() -> dict:
|
|
|
965
1104
|
"global_options": {
|
|
966
1105
|
"--api-key": "Override API key (env: MEM0_API_KEY).",
|
|
967
1106
|
"--base-url": "Override API base URL.",
|
|
1107
|
+
"--json / --agent": "Output as JSON for agent/programmatic use.",
|
|
968
1108
|
"--help": "Show help for a command.",
|
|
969
1109
|
"--version": "Show version and exit.",
|
|
970
1110
|
},
|
|
@@ -994,7 +1134,7 @@ def help(
|
|
|
994
1134
|
console.print("Usage: mem0 <command> [OPTIONS]\n")
|
|
995
1135
|
console.print("[bold]Commands:[/]")
|
|
996
1136
|
console.print(" add Add a memory from text, messages, file, or stdin")
|
|
997
|
-
console.print(" search
|
|
1137
|
+
console.print(" search Query your memory store (semantic, keyword, hybrid)")
|
|
998
1138
|
console.print(" get Get a specific memory by ID")
|
|
999
1139
|
console.print(" list List memories with optional filters")
|
|
1000
1140
|
console.print(" update Update a memory's text or metadata")
|
|
@@ -1002,6 +1142,7 @@ def help(
|
|
|
1002
1142
|
console.print(" import Import memories from a JSON file")
|
|
1003
1143
|
console.print(" config Manage configuration (show, get, set)")
|
|
1004
1144
|
console.print(" entity Manage entities (list, delete)")
|
|
1145
|
+
console.print(" event Inspect background events (list, status)")
|
|
1005
1146
|
console.print(" init Interactive setup wizard")
|
|
1006
1147
|
console.print(" status Check connectivity and authentication")
|
|
1007
1148
|
console.print()
|
|
@@ -1018,4 +1159,14 @@ app.add_typer(config_app, name="config", rich_help_panel="Management")
|
|
|
1018
1159
|
|
|
1019
1160
|
|
|
1020
1161
|
def main() -> None:
|
|
1162
|
+
import sys
|
|
1163
|
+
|
|
1164
|
+
# Allow --json/--agent anywhere in the command line (not just before subcommand).
|
|
1165
|
+
_json_flags = {"--json", "--agent"}
|
|
1166
|
+
if any(a in _json_flags for a in sys.argv[1:]):
|
|
1167
|
+
from mem0_cli.state import set_agent_mode
|
|
1168
|
+
|
|
1169
|
+
set_agent_mode(True)
|
|
1170
|
+
sys.argv = [sys.argv[0]] + [a for a in sys.argv[1:] if a not in _json_flags]
|
|
1171
|
+
|
|
1021
1172
|
app()
|
|
@@ -104,6 +104,11 @@ class Backend(ABC):
|
|
|
104
104
|
@abstractmethod
|
|
105
105
|
def entities(self, entity_type: str) -> list[dict]: ...
|
|
106
106
|
|
|
107
|
+
@abstractmethod
|
|
108
|
+
def list_events(self) -> list[dict]: ...
|
|
109
|
+
|
|
110
|
+
@abstractmethod
|
|
111
|
+
def get_event(self, event_id: str) -> dict: ...
|
|
107
112
|
|
|
108
113
|
|
|
109
114
|
def get_backend(config: Mem0Config) -> Backend:
|