mem0-cli 0.1.0__py3-none-any.whl
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/__init__.py +3 -0
- mem0_cli/__main__.py +5 -0
- mem0_cli/app.py +1021 -0
- mem0_cli/backend/__init__.py +5 -0
- mem0_cli/backend/base.py +113 -0
- mem0_cli/backend/platform.py +325 -0
- mem0_cli/branding.py +130 -0
- mem0_cli/commands/__init__.py +1 -0
- mem0_cli/commands/config_cmd.py +108 -0
- mem0_cli/commands/entities.py +133 -0
- mem0_cli/commands/init_cmd.py +195 -0
- mem0_cli/commands/memory.py +469 -0
- mem0_cli/commands/utils.py +142 -0
- mem0_cli/config.py +176 -0
- mem0_cli/output.py +242 -0
- mem0_cli-0.1.0.dist-info/METADATA +57 -0
- mem0_cli-0.1.0.dist-info/RECORD +19 -0
- mem0_cli-0.1.0.dist-info/WHEEL +4 -0
- mem0_cli-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
"""Memory CRUD commands: add, search, get, list, update, delete."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
import time as _time
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import typer
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
|
|
13
|
+
from mem0_cli.backend.base import Backend
|
|
14
|
+
from mem0_cli.branding import (
|
|
15
|
+
print_error,
|
|
16
|
+
print_info,
|
|
17
|
+
print_scope,
|
|
18
|
+
print_success,
|
|
19
|
+
timed_status,
|
|
20
|
+
)
|
|
21
|
+
from mem0_cli.output import (
|
|
22
|
+
format_add_result,
|
|
23
|
+
format_json,
|
|
24
|
+
format_memories_table,
|
|
25
|
+
format_memories_text,
|
|
26
|
+
format_single_memory,
|
|
27
|
+
print_result_summary,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
console = Console()
|
|
31
|
+
err_console = Console(stderr=True)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def cmd_add(
|
|
35
|
+
backend: Backend,
|
|
36
|
+
text: str | None,
|
|
37
|
+
*,
|
|
38
|
+
user_id: str | None,
|
|
39
|
+
agent_id: str | None,
|
|
40
|
+
app_id: str | None,
|
|
41
|
+
run_id: str | None,
|
|
42
|
+
messages: str | None,
|
|
43
|
+
file: Path | None,
|
|
44
|
+
metadata: str | None,
|
|
45
|
+
immutable: bool,
|
|
46
|
+
no_infer: bool,
|
|
47
|
+
expires: str | None,
|
|
48
|
+
categories: str | None,
|
|
49
|
+
enable_graph: bool = False,
|
|
50
|
+
output: str = "text",
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Add a memory."""
|
|
53
|
+
msgs = None
|
|
54
|
+
content = text
|
|
55
|
+
|
|
56
|
+
# Read from file
|
|
57
|
+
if file:
|
|
58
|
+
try:
|
|
59
|
+
raw = Path(file).read_text()
|
|
60
|
+
msgs = json.loads(raw)
|
|
61
|
+
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
62
|
+
print_error(err_console, f"Failed to read file: {e}")
|
|
63
|
+
raise typer.Exit(1) from None
|
|
64
|
+
|
|
65
|
+
# Parse messages JSON
|
|
66
|
+
elif messages:
|
|
67
|
+
try:
|
|
68
|
+
msgs = json.loads(messages)
|
|
69
|
+
except json.JSONDecodeError as e:
|
|
70
|
+
print_error(err_console, f"Invalid JSON in --messages: {e}")
|
|
71
|
+
raise typer.Exit(1) from None
|
|
72
|
+
|
|
73
|
+
# Read from stdin if no text and stdin is piped
|
|
74
|
+
elif not content and not sys.stdin.isatty():
|
|
75
|
+
content = sys.stdin.read().strip()
|
|
76
|
+
|
|
77
|
+
if not content and not msgs:
|
|
78
|
+
print_error(
|
|
79
|
+
err_console, "No content provided. Pass text, --messages, --file, or pipe via stdin."
|
|
80
|
+
)
|
|
81
|
+
raise typer.Exit(1)
|
|
82
|
+
|
|
83
|
+
meta = None
|
|
84
|
+
if metadata:
|
|
85
|
+
try:
|
|
86
|
+
meta = json.loads(metadata)
|
|
87
|
+
except json.JSONDecodeError:
|
|
88
|
+
print_error(err_console, "Invalid JSON in --metadata.")
|
|
89
|
+
raise typer.Exit(1) from None
|
|
90
|
+
|
|
91
|
+
cats = None
|
|
92
|
+
if categories:
|
|
93
|
+
try:
|
|
94
|
+
cats = json.loads(categories)
|
|
95
|
+
except json.JSONDecodeError:
|
|
96
|
+
cats = [c.strip() for c in categories.split(",")]
|
|
97
|
+
|
|
98
|
+
with timed_status(err_console, "Adding memory...") as ts:
|
|
99
|
+
try:
|
|
100
|
+
result = backend.add(
|
|
101
|
+
content=content,
|
|
102
|
+
messages=msgs,
|
|
103
|
+
user_id=user_id,
|
|
104
|
+
agent_id=agent_id,
|
|
105
|
+
app_id=app_id,
|
|
106
|
+
run_id=run_id,
|
|
107
|
+
metadata=meta,
|
|
108
|
+
immutable=immutable,
|
|
109
|
+
infer=not no_infer,
|
|
110
|
+
expires=expires,
|
|
111
|
+
categories=cats,
|
|
112
|
+
enable_graph=enable_graph,
|
|
113
|
+
)
|
|
114
|
+
except Exception as e:
|
|
115
|
+
ts.error_msg = str(e)
|
|
116
|
+
print_error(err_console, str(e))
|
|
117
|
+
raise typer.Exit(1) from None
|
|
118
|
+
|
|
119
|
+
if output == "quiet":
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
if output == "json":
|
|
123
|
+
format_add_result(console, result, output)
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
console.print()
|
|
127
|
+
print_scope(console, user_id=user_id, agent_id=agent_id, app_id=app_id, run_id=run_id)
|
|
128
|
+
# Count results
|
|
129
|
+
results = result if isinstance(result, list) else result.get("results", [result])
|
|
130
|
+
count = len(results) if results else 0
|
|
131
|
+
print_success(
|
|
132
|
+
console, f"Memory processed — {count} memor{'y' if count == 1 else 'ies'} extracted"
|
|
133
|
+
)
|
|
134
|
+
format_add_result(console, result, output)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def cmd_search(
|
|
138
|
+
backend: Backend,
|
|
139
|
+
query: str,
|
|
140
|
+
*,
|
|
141
|
+
user_id: str | None,
|
|
142
|
+
agent_id: str | None,
|
|
143
|
+
app_id: str | None,
|
|
144
|
+
run_id: str | None,
|
|
145
|
+
top_k: int,
|
|
146
|
+
threshold: float,
|
|
147
|
+
rerank: bool,
|
|
148
|
+
keyword: bool,
|
|
149
|
+
filter_json: str | None,
|
|
150
|
+
fields: str | None,
|
|
151
|
+
enable_graph: bool = False,
|
|
152
|
+
output: str = "text",
|
|
153
|
+
) -> None:
|
|
154
|
+
"""Search memories."""
|
|
155
|
+
filters = None
|
|
156
|
+
if filter_json:
|
|
157
|
+
try:
|
|
158
|
+
filters = json.loads(filter_json)
|
|
159
|
+
except json.JSONDecodeError:
|
|
160
|
+
print_error(err_console, "Invalid JSON in --filter.")
|
|
161
|
+
raise typer.Exit(1) from None
|
|
162
|
+
|
|
163
|
+
field_list = None
|
|
164
|
+
if fields:
|
|
165
|
+
field_list = [f.strip() for f in fields.split(",")]
|
|
166
|
+
|
|
167
|
+
_start = _time.perf_counter()
|
|
168
|
+
with timed_status(err_console, "Searching memories...") as _ts:
|
|
169
|
+
try:
|
|
170
|
+
results = backend.search(
|
|
171
|
+
query,
|
|
172
|
+
user_id=user_id,
|
|
173
|
+
agent_id=agent_id,
|
|
174
|
+
app_id=app_id,
|
|
175
|
+
run_id=run_id,
|
|
176
|
+
top_k=top_k,
|
|
177
|
+
threshold=threshold,
|
|
178
|
+
rerank=rerank,
|
|
179
|
+
keyword=keyword,
|
|
180
|
+
filters=filters,
|
|
181
|
+
fields=field_list,
|
|
182
|
+
enable_graph=enable_graph,
|
|
183
|
+
)
|
|
184
|
+
except Exception as e:
|
|
185
|
+
print_error(err_console, str(e))
|
|
186
|
+
raise typer.Exit(1) from None
|
|
187
|
+
_elapsed = _time.perf_counter() - _start
|
|
188
|
+
|
|
189
|
+
if output == "json":
|
|
190
|
+
format_json(console, results)
|
|
191
|
+
elif output == "table":
|
|
192
|
+
if results:
|
|
193
|
+
format_memories_table(console, results)
|
|
194
|
+
print_result_summary(
|
|
195
|
+
console, len(results), duration_secs=_elapsed, user_id=user_id, agent_id=agent_id
|
|
196
|
+
)
|
|
197
|
+
else:
|
|
198
|
+
console.print()
|
|
199
|
+
print_info(console, "No memories found matching your query.")
|
|
200
|
+
console.print()
|
|
201
|
+
else:
|
|
202
|
+
if results:
|
|
203
|
+
format_memories_text(console, results)
|
|
204
|
+
print_result_summary(
|
|
205
|
+
console, len(results), duration_secs=_elapsed, user_id=user_id, agent_id=agent_id
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
console.print()
|
|
209
|
+
print_info(console, "No memories found matching your query.")
|
|
210
|
+
console.print()
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def cmd_get(backend: Backend, memory_id: str, *, output: str) -> None:
|
|
214
|
+
"""Get a specific memory by ID."""
|
|
215
|
+
with timed_status(err_console, "Fetching memory...") as _ts:
|
|
216
|
+
try:
|
|
217
|
+
result = backend.get(memory_id)
|
|
218
|
+
except Exception as e:
|
|
219
|
+
print_error(err_console, str(e))
|
|
220
|
+
raise typer.Exit(1) from None
|
|
221
|
+
|
|
222
|
+
format_single_memory(console, result, output)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def cmd_list(
|
|
226
|
+
backend: Backend,
|
|
227
|
+
*,
|
|
228
|
+
user_id: str | None,
|
|
229
|
+
agent_id: str | None,
|
|
230
|
+
app_id: str | None,
|
|
231
|
+
run_id: str | None,
|
|
232
|
+
page: int,
|
|
233
|
+
page_size: int,
|
|
234
|
+
category: str | None,
|
|
235
|
+
after: str | None,
|
|
236
|
+
before: str | None,
|
|
237
|
+
enable_graph: bool = False,
|
|
238
|
+
output: str = "table",
|
|
239
|
+
) -> None:
|
|
240
|
+
"""List memories."""
|
|
241
|
+
_start = _time.perf_counter()
|
|
242
|
+
with timed_status(err_console, "Listing memories...") as _ts:
|
|
243
|
+
try:
|
|
244
|
+
results = backend.list_memories(
|
|
245
|
+
user_id=user_id,
|
|
246
|
+
agent_id=agent_id,
|
|
247
|
+
app_id=app_id,
|
|
248
|
+
run_id=run_id,
|
|
249
|
+
page=page,
|
|
250
|
+
page_size=page_size,
|
|
251
|
+
category=category,
|
|
252
|
+
after=after,
|
|
253
|
+
before=before,
|
|
254
|
+
enable_graph=enable_graph,
|
|
255
|
+
)
|
|
256
|
+
except Exception as e:
|
|
257
|
+
print_error(err_console, str(e))
|
|
258
|
+
raise typer.Exit(1) from None
|
|
259
|
+
_elapsed = _time.perf_counter() - _start
|
|
260
|
+
|
|
261
|
+
if output == "json":
|
|
262
|
+
format_json(console, results)
|
|
263
|
+
elif output == "table":
|
|
264
|
+
if results:
|
|
265
|
+
format_memories_table(console, results)
|
|
266
|
+
print_result_summary(
|
|
267
|
+
console,
|
|
268
|
+
len(results),
|
|
269
|
+
duration_secs=_elapsed,
|
|
270
|
+
page=page,
|
|
271
|
+
user_id=user_id,
|
|
272
|
+
agent_id=agent_id,
|
|
273
|
+
)
|
|
274
|
+
else:
|
|
275
|
+
console.print()
|
|
276
|
+
print_info(console, "No memories found.")
|
|
277
|
+
console.print()
|
|
278
|
+
else:
|
|
279
|
+
if results:
|
|
280
|
+
format_memories_text(console, results, title="memories")
|
|
281
|
+
print_result_summary(
|
|
282
|
+
console,
|
|
283
|
+
len(results),
|
|
284
|
+
duration_secs=_elapsed,
|
|
285
|
+
page=page,
|
|
286
|
+
user_id=user_id,
|
|
287
|
+
agent_id=agent_id,
|
|
288
|
+
)
|
|
289
|
+
else:
|
|
290
|
+
console.print()
|
|
291
|
+
print_info(console, "No memories found.")
|
|
292
|
+
console.print()
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def cmd_update(
|
|
296
|
+
backend: Backend,
|
|
297
|
+
memory_id: str,
|
|
298
|
+
text: str | None,
|
|
299
|
+
*,
|
|
300
|
+
metadata: str | None,
|
|
301
|
+
output: str,
|
|
302
|
+
) -> None:
|
|
303
|
+
"""Update a memory."""
|
|
304
|
+
meta = None
|
|
305
|
+
if metadata:
|
|
306
|
+
try:
|
|
307
|
+
meta = json.loads(metadata)
|
|
308
|
+
except json.JSONDecodeError:
|
|
309
|
+
print_error(err_console, "Invalid JSON in --metadata.")
|
|
310
|
+
raise typer.Exit(1) from None
|
|
311
|
+
|
|
312
|
+
_start = _time.perf_counter()
|
|
313
|
+
with timed_status(err_console, "Updating memory...") as _ts:
|
|
314
|
+
try:
|
|
315
|
+
result = backend.update(memory_id, content=text, metadata=meta)
|
|
316
|
+
except Exception as e:
|
|
317
|
+
print_error(err_console, str(e))
|
|
318
|
+
raise typer.Exit(1) from None
|
|
319
|
+
_elapsed = _time.perf_counter() - _start
|
|
320
|
+
|
|
321
|
+
if output == "json":
|
|
322
|
+
format_json(console, result)
|
|
323
|
+
elif output != "quiet":
|
|
324
|
+
print_success(console, f"Memory {memory_id[:8]} updated ({_elapsed:.2f}s)")
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def cmd_delete(
|
|
328
|
+
backend: Backend,
|
|
329
|
+
memory_id: str,
|
|
330
|
+
*,
|
|
331
|
+
dry_run: bool = False,
|
|
332
|
+
force: bool = False,
|
|
333
|
+
output: str,
|
|
334
|
+
) -> None:
|
|
335
|
+
"""Delete a single memory by ID."""
|
|
336
|
+
if dry_run:
|
|
337
|
+
# Fetch and display what would be deleted
|
|
338
|
+
try:
|
|
339
|
+
mem = backend.get(memory_id)
|
|
340
|
+
except Exception as e:
|
|
341
|
+
print_error(err_console, str(e))
|
|
342
|
+
raise typer.Exit(1) from None
|
|
343
|
+
format_single_memory(console, mem, output)
|
|
344
|
+
print_info(console, "No changes made (dry run).")
|
|
345
|
+
return
|
|
346
|
+
|
|
347
|
+
_start = _time.perf_counter()
|
|
348
|
+
with timed_status(err_console, "Deleting...") as _ts:
|
|
349
|
+
try:
|
|
350
|
+
result = backend.delete(memory_id=memory_id)
|
|
351
|
+
except Exception as e:
|
|
352
|
+
print_error(err_console, str(e))
|
|
353
|
+
raise typer.Exit(1) from None
|
|
354
|
+
_elapsed = _time.perf_counter() - _start
|
|
355
|
+
|
|
356
|
+
if output == "json":
|
|
357
|
+
format_json(console, result)
|
|
358
|
+
elif output != "quiet":
|
|
359
|
+
print_success(console, f"Memory {memory_id[:8]} deleted ({_elapsed:.2f}s)")
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def cmd_delete_all(
|
|
363
|
+
backend: Backend,
|
|
364
|
+
*,
|
|
365
|
+
force: bool,
|
|
366
|
+
dry_run: bool = False,
|
|
367
|
+
all_: bool = False,
|
|
368
|
+
user_id: str | None,
|
|
369
|
+
agent_id: str | None,
|
|
370
|
+
app_id: str | None,
|
|
371
|
+
run_id: str | None,
|
|
372
|
+
output: str,
|
|
373
|
+
) -> None:
|
|
374
|
+
"""Delete all memories matching a scope."""
|
|
375
|
+
if all_:
|
|
376
|
+
# Project-wide wipe using wildcard entity IDs
|
|
377
|
+
if dry_run:
|
|
378
|
+
print_info(console, "Would delete ALL memories project-wide.")
|
|
379
|
+
print_info(console, "No changes made (dry run).")
|
|
380
|
+
return
|
|
381
|
+
|
|
382
|
+
if not force:
|
|
383
|
+
confirm = typer.confirm(
|
|
384
|
+
"\n ⚠ Delete ALL memories across the ENTIRE project? This cannot be undone."
|
|
385
|
+
)
|
|
386
|
+
if not confirm:
|
|
387
|
+
print_info(console, "Cancelled.")
|
|
388
|
+
raise typer.Exit(0)
|
|
389
|
+
|
|
390
|
+
_start = _time.perf_counter()
|
|
391
|
+
with timed_status(err_console, "Deleting all memories project-wide...") as _ts:
|
|
392
|
+
try:
|
|
393
|
+
result = backend.delete(
|
|
394
|
+
all=True,
|
|
395
|
+
user_id="*",
|
|
396
|
+
agent_id="*",
|
|
397
|
+
app_id="*",
|
|
398
|
+
run_id="*",
|
|
399
|
+
)
|
|
400
|
+
except Exception as e:
|
|
401
|
+
print_error(err_console, str(e))
|
|
402
|
+
raise typer.Exit(1) from None
|
|
403
|
+
_elapsed = _time.perf_counter() - _start
|
|
404
|
+
|
|
405
|
+
if output == "json":
|
|
406
|
+
format_json(console, result)
|
|
407
|
+
elif output != "quiet":
|
|
408
|
+
if isinstance(result, dict) and "message" in result:
|
|
409
|
+
print_info(console, "Deletion started. Memories will be removed in the background.")
|
|
410
|
+
else:
|
|
411
|
+
print_success(console, f"All project memories deleted ({_elapsed:.2f}s)")
|
|
412
|
+
return
|
|
413
|
+
|
|
414
|
+
if dry_run:
|
|
415
|
+
# List matching memories and show count
|
|
416
|
+
try:
|
|
417
|
+
results = backend.list_memories(
|
|
418
|
+
user_id=user_id,
|
|
419
|
+
agent_id=agent_id,
|
|
420
|
+
app_id=app_id,
|
|
421
|
+
run_id=run_id,
|
|
422
|
+
)
|
|
423
|
+
except Exception as e:
|
|
424
|
+
print_error(err_console, str(e))
|
|
425
|
+
raise typer.Exit(1) from None
|
|
426
|
+
count = len(results)
|
|
427
|
+
print_info(console, f"Would delete {count} memor{'y' if count == 1 else 'ies'}.")
|
|
428
|
+
print_info(console, "No changes made (dry run).")
|
|
429
|
+
return
|
|
430
|
+
|
|
431
|
+
if not force:
|
|
432
|
+
scope_parts = []
|
|
433
|
+
if user_id:
|
|
434
|
+
scope_parts.append(f"user={user_id}")
|
|
435
|
+
if agent_id:
|
|
436
|
+
scope_parts.append(f"agent={agent_id}")
|
|
437
|
+
if app_id:
|
|
438
|
+
scope_parts.append(f"app={app_id}")
|
|
439
|
+
if run_id:
|
|
440
|
+
scope_parts.append(f"run={run_id}")
|
|
441
|
+
scope = ", ".join(scope_parts) if scope_parts else "ALL entities"
|
|
442
|
+
|
|
443
|
+
confirm = typer.confirm(f"\n ⚠ Delete ALL memories for {scope}? This cannot be undone.")
|
|
444
|
+
if not confirm:
|
|
445
|
+
print_info(console, "Cancelled.")
|
|
446
|
+
raise typer.Exit(0)
|
|
447
|
+
|
|
448
|
+
_start = _time.perf_counter()
|
|
449
|
+
with timed_status(err_console, "Deleting all memories...") as _ts:
|
|
450
|
+
try:
|
|
451
|
+
result = backend.delete(
|
|
452
|
+
all=True,
|
|
453
|
+
user_id=user_id,
|
|
454
|
+
agent_id=agent_id,
|
|
455
|
+
app_id=app_id,
|
|
456
|
+
run_id=run_id,
|
|
457
|
+
)
|
|
458
|
+
except Exception as e:
|
|
459
|
+
print_error(err_console, str(e))
|
|
460
|
+
raise typer.Exit(1) from None
|
|
461
|
+
_elapsed = _time.perf_counter() - _start
|
|
462
|
+
|
|
463
|
+
if output == "json":
|
|
464
|
+
format_json(console, result)
|
|
465
|
+
elif output != "quiet":
|
|
466
|
+
if isinstance(result, dict) and "message" in result:
|
|
467
|
+
print_info(console, "Deletion started. Memories will be removed in the background.")
|
|
468
|
+
else:
|
|
469
|
+
print_success(console, f"All matching memories deleted ({_elapsed:.2f}s)")
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Utility commands: status, version, import."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import time as _time
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from rich.panel import Panel
|
|
12
|
+
from rich.progress import track
|
|
13
|
+
|
|
14
|
+
from mem0_cli import __version__
|
|
15
|
+
from mem0_cli.backend.base import Backend
|
|
16
|
+
from mem0_cli.branding import (
|
|
17
|
+
BRAND_COLOR,
|
|
18
|
+
DIM_COLOR,
|
|
19
|
+
ERROR_COLOR,
|
|
20
|
+
SUCCESS_COLOR,
|
|
21
|
+
print_error,
|
|
22
|
+
print_success,
|
|
23
|
+
timed_status,
|
|
24
|
+
)
|
|
25
|
+
from mem0_cli.config import load_config
|
|
26
|
+
|
|
27
|
+
console = Console()
|
|
28
|
+
err_console = Console(stderr=True)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def cmd_status(
|
|
32
|
+
backend: Backend,
|
|
33
|
+
*,
|
|
34
|
+
user_id: str | None = None,
|
|
35
|
+
agent_id: str | None = None,
|
|
36
|
+
output: str = "text",
|
|
37
|
+
) -> None:
|
|
38
|
+
"""Check connectivity and auth."""
|
|
39
|
+
from mem0_cli.output import format_json_envelope
|
|
40
|
+
|
|
41
|
+
_start = _time.perf_counter()
|
|
42
|
+
with timed_status(err_console, "Checking connection...") as _ts:
|
|
43
|
+
result = backend.status(user_id=user_id, agent_id=agent_id)
|
|
44
|
+
_elapsed = _time.perf_counter() - _start
|
|
45
|
+
|
|
46
|
+
if output == "json":
|
|
47
|
+
format_json_envelope(
|
|
48
|
+
console,
|
|
49
|
+
command="status",
|
|
50
|
+
data={
|
|
51
|
+
"connected": result.get("connected", False),
|
|
52
|
+
"backend": result.get("backend", "?"),
|
|
53
|
+
"base_url": result.get("base_url", ""),
|
|
54
|
+
"latency_ms": int(_elapsed * 1000),
|
|
55
|
+
},
|
|
56
|
+
duration_ms=int(_elapsed * 1000),
|
|
57
|
+
)
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
lines = []
|
|
61
|
+
if result.get("connected"):
|
|
62
|
+
lines.append(f" [{SUCCESS_COLOR}]●[/] Connected")
|
|
63
|
+
else:
|
|
64
|
+
lines.append(f" [{ERROR_COLOR}]●[/] Disconnected")
|
|
65
|
+
|
|
66
|
+
lines.append(f" [{DIM_COLOR}]Backend:[/] {result.get('backend', '?')}")
|
|
67
|
+
if result.get("base_url"):
|
|
68
|
+
lines.append(f" [{DIM_COLOR}]API URL:[/] {result['base_url']}")
|
|
69
|
+
if result.get("error"):
|
|
70
|
+
lines.append(f" [{ERROR_COLOR}]Error:[/] {result['error']}")
|
|
71
|
+
lines.append(f" [{DIM_COLOR}]Latency:[/] {_elapsed:.2f}s")
|
|
72
|
+
|
|
73
|
+
content = "\n".join(lines)
|
|
74
|
+
panel = Panel(
|
|
75
|
+
content,
|
|
76
|
+
title=f"[{BRAND_COLOR}]Connection Status[/]",
|
|
77
|
+
title_align="left",
|
|
78
|
+
border_style=BRAND_COLOR,
|
|
79
|
+
padding=(1, 1),
|
|
80
|
+
)
|
|
81
|
+
console.print()
|
|
82
|
+
console.print(panel)
|
|
83
|
+
console.print()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def cmd_version() -> None:
|
|
87
|
+
"""Show version."""
|
|
88
|
+
console.print(f" [{BRAND_COLOR}]◆ Mem0[/] CLI v{__version__}")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def cmd_import(
|
|
92
|
+
backend: Backend,
|
|
93
|
+
file_path: str,
|
|
94
|
+
*,
|
|
95
|
+
user_id: str | None,
|
|
96
|
+
agent_id: str | None,
|
|
97
|
+
output: str = "text",
|
|
98
|
+
) -> None:
|
|
99
|
+
"""Import memories from a JSON file."""
|
|
100
|
+
from mem0_cli.output import format_json_envelope
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
data = json.loads(Path(file_path).read_text())
|
|
104
|
+
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
105
|
+
print_error(err_console, f"Failed to read file: {e}")
|
|
106
|
+
raise typer.Exit(1) from None
|
|
107
|
+
|
|
108
|
+
if not isinstance(data, list):
|
|
109
|
+
data = [data]
|
|
110
|
+
|
|
111
|
+
added = 0
|
|
112
|
+
failed = 0
|
|
113
|
+
_start = _time.perf_counter()
|
|
114
|
+
for item in track(data, description=f"[{DIM_COLOR}]Importing memories...[/]", console=err_console):
|
|
115
|
+
content = item.get("memory", item.get("text", item.get("content", "")))
|
|
116
|
+
if not content:
|
|
117
|
+
failed += 1
|
|
118
|
+
continue
|
|
119
|
+
try:
|
|
120
|
+
backend.add(
|
|
121
|
+
content=content,
|
|
122
|
+
user_id=user_id or item.get("user_id"),
|
|
123
|
+
agent_id=agent_id or item.get("agent_id"),
|
|
124
|
+
metadata=item.get("metadata"),
|
|
125
|
+
)
|
|
126
|
+
added += 1
|
|
127
|
+
except Exception:
|
|
128
|
+
failed += 1
|
|
129
|
+
_elapsed = _time.perf_counter() - _start
|
|
130
|
+
|
|
131
|
+
if output == "json":
|
|
132
|
+
format_json_envelope(
|
|
133
|
+
console,
|
|
134
|
+
command="import",
|
|
135
|
+
data={"added": added, "failed": failed, "duration_s": round(_elapsed, 2)},
|
|
136
|
+
duration_ms=int(_elapsed * 1000),
|
|
137
|
+
)
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
print_success(err_console, f"Imported {added} memories ({_elapsed:.2f}s)")
|
|
141
|
+
if failed:
|
|
142
|
+
print_error(err_console, f"{failed} memories failed to import.")
|