mem0-cli 0.2.5__tar.gz → 0.2.7__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.5 → mem0_cli-0.2.7}/PKG-INFO +1 -1
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/pyproject.toml +1 -1
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/app.py +59 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/agent_mode_cmd.py +1 -1
- mem0_cli-0.2.7/src/mem0_cli/commands/agent_rush_cmd.py +132 -0
- mem0_cli-0.2.7/src/mem0_cli/commands/whoami_cmd.py +25 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/config.py +14 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/.gitignore +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/README.md +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/__init__.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/__main__.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/agent_detect.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/backend/__init__.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/backend/base.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/backend/platform.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/branding.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/__init__.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/config_cmd.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/entities.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/events_cmd.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/identify_cmd.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/init_cmd.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/memory.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/commands/utils.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/output.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/plugin_sync.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/state.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/telemetry.py +0 -0
- {mem0_cli-0.2.5 → mem0_cli-0.2.7}/src/mem0_cli/telemetry_sender.py +0 -0
|
@@ -914,6 +914,65 @@ def identify(
|
|
|
914
914
|
run_identify(name)
|
|
915
915
|
|
|
916
916
|
|
|
917
|
+
@app.command(name="whoami", rich_help_panel="Setup")
|
|
918
|
+
def whoami_cmd() -> None:
|
|
919
|
+
"""Print your AGENTRUSH identifier (default_user_id).
|
|
920
|
+
|
|
921
|
+
Example:
|
|
922
|
+
mem0 whoami
|
|
923
|
+
"""
|
|
924
|
+
from mem0_cli.commands.whoami_cmd import run_whoami
|
|
925
|
+
|
|
926
|
+
run_whoami()
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
# ── AGENTRUSH sub-app ─────────────────────────────────────────────────────
|
|
930
|
+
|
|
931
|
+
agent_rush_app = typer.Typer(
|
|
932
|
+
name="agent-rush",
|
|
933
|
+
help="AGENTRUSH game commands",
|
|
934
|
+
no_args_is_help=True,
|
|
935
|
+
rich_markup_mode="rich",
|
|
936
|
+
)
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
@agent_rush_app.callback(invoke_without_command=True)
|
|
940
|
+
def _agent_rush_callback(ctx: typer.Context) -> None:
|
|
941
|
+
if ctx.invoked_subcommand:
|
|
942
|
+
_fire_telemetry(f"agent-rush.{ctx.invoked_subcommand}")
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
@agent_rush_app.command(name="add")
|
|
946
|
+
def agent_rush_add(
|
|
947
|
+
content: str = typer.Argument(..., help="Memory content (50-1000 characters, no URLs)."),
|
|
948
|
+
) -> None:
|
|
949
|
+
"""Submit a memory to AGENTRUSH.
|
|
950
|
+
|
|
951
|
+
Example:
|
|
952
|
+
mem0 agent-rush add "I enjoy solving constraint-satisfaction problems."
|
|
953
|
+
"""
|
|
954
|
+
from mem0_cli.commands.agent_rush_cmd import run_agent_rush_add
|
|
955
|
+
|
|
956
|
+
run_agent_rush_add(content)
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
@agent_rush_app.command(name="search")
|
|
960
|
+
def agent_rush_search(
|
|
961
|
+
query: str = typer.Argument(..., help="Search query."),
|
|
962
|
+
) -> None:
|
|
963
|
+
"""Search AGENTRUSH memories.
|
|
964
|
+
|
|
965
|
+
Example:
|
|
966
|
+
mem0 agent-rush search "constraint satisfaction"
|
|
967
|
+
"""
|
|
968
|
+
from mem0_cli.commands.agent_rush_cmd import run_agent_rush_search
|
|
969
|
+
|
|
970
|
+
run_agent_rush_search(query)
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
app.add_typer(agent_rush_app, name="agent-rush", rich_help_panel="Setup")
|
|
974
|
+
|
|
975
|
+
|
|
917
976
|
# (entity_app registered at module level, below sub-group definitions)
|
|
918
977
|
|
|
919
978
|
|
|
@@ -218,7 +218,7 @@ def claim_via_otp(config: Mem0Config, *, email: str, code: str | None = None) ->
|
|
|
218
218
|
print_error(err_console, f"Claim failed: {detail}")
|
|
219
219
|
if code_str == "email_already_claimed":
|
|
220
220
|
console.print(
|
|
221
|
-
f" [{DIM_COLOR}]Tip: this email already has a Mem0 account. Sign in
|
|
221
|
+
f" [{DIM_COLOR}]Tip: this email already has a Mem0 account. Sign in at app.mem0.ai with your existing credentials.[/]"
|
|
222
222
|
)
|
|
223
223
|
raise typer.Exit(1)
|
|
224
224
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""mem0 agent-rush — AGENTRUSH game commands.
|
|
2
|
+
|
|
3
|
+
Wraps the platform's /v1/agent-rush/{memories/, memories/search/} endpoints.
|
|
4
|
+
Hardcoded routing; no flags needed.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
|
|
12
|
+
import httpx
|
|
13
|
+
import typer
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
|
|
16
|
+
from mem0_cli.branding import print_error, print_success
|
|
17
|
+
from mem0_cli.config import load_config, save_config
|
|
18
|
+
|
|
19
|
+
console = Console()
|
|
20
|
+
err_console = Console(stderr=True)
|
|
21
|
+
|
|
22
|
+
_PII_WARNING_LINES = (
|
|
23
|
+
"",
|
|
24
|
+
"[yellow]⚠️ AGENTRUSH memories are PUBLIC — visible to any other player.[/yellow]",
|
|
25
|
+
"[yellow] Do not include real names, emails, secrets, work content, or PII.[/yellow]",
|
|
26
|
+
"",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
_SOURCE_HEADERS = {
|
|
30
|
+
"X-Mem0-Source": "cli",
|
|
31
|
+
"X-Mem0-Client-Language": "python",
|
|
32
|
+
"X-Mem0-Mode": "agent-rush",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_ERROR_HINTS = {
|
|
36
|
+
"agentrush_search_first": "Run 3 'mem0 agent-rush search' commands before adding.",
|
|
37
|
+
"agentrush_search_quota": "You've used your 3 lifetime searches.",
|
|
38
|
+
"agentrush_add_quota": "You've used your 3 lifetime adds.",
|
|
39
|
+
"agentrush_not_agent_mode": "Re-run 'mem0 init --agent' to bootstrap an agent-mode key.",
|
|
40
|
+
"agentrush_length": "Memory text must be 50-1000 characters.",
|
|
41
|
+
"agentrush_no_urls": "URLs are not allowed.",
|
|
42
|
+
"agentrush_blocklist": "Content contains a blocked term.",
|
|
43
|
+
"agentrush_global_quota": "Event-wide cap reached. Try again later.",
|
|
44
|
+
"agentrush_not_provisioned": "AGENTRUSH is not provisioned in this environment.",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _call(path: str, body: dict) -> dict:
|
|
49
|
+
config = load_config()
|
|
50
|
+
if not config.platform.api_key:
|
|
51
|
+
print_error(err_console, "Not initialized. Run `mem0 init --agent` first.")
|
|
52
|
+
raise typer.Exit(1)
|
|
53
|
+
base_url = (config.platform.base_url or "https://api.mem0.ai").rstrip("/")
|
|
54
|
+
try:
|
|
55
|
+
with httpx.Client(timeout=30.0) as client:
|
|
56
|
+
resp = client.post(
|
|
57
|
+
f"{base_url}{path}",
|
|
58
|
+
headers={
|
|
59
|
+
**_SOURCE_HEADERS,
|
|
60
|
+
"Authorization": f"Token {config.platform.api_key}",
|
|
61
|
+
"Content-Type": "application/json",
|
|
62
|
+
},
|
|
63
|
+
json=body,
|
|
64
|
+
)
|
|
65
|
+
except httpx.HTTPError as exc:
|
|
66
|
+
print_error(err_console, f"Network error: {exc}")
|
|
67
|
+
raise typer.Exit(1) from exc
|
|
68
|
+
try:
|
|
69
|
+
data = resp.json()
|
|
70
|
+
except Exception:
|
|
71
|
+
data = {}
|
|
72
|
+
if resp.status_code >= 400:
|
|
73
|
+
code = (
|
|
74
|
+
(data.get("error") or {}).get("code", "unknown")
|
|
75
|
+
if isinstance(data, dict)
|
|
76
|
+
else "unknown"
|
|
77
|
+
)
|
|
78
|
+
print_error(err_console, f"AGENTRUSH error: {code}")
|
|
79
|
+
hint = _ERROR_HINTS.get(code)
|
|
80
|
+
if hint:
|
|
81
|
+
console.print(f" [dim]{hint}[/dim]")
|
|
82
|
+
raise typer.Exit(1)
|
|
83
|
+
return data
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _ensure_warning_acknowledged() -> None:
|
|
87
|
+
"""Block the first interactive add on the PII warning; pass-through for agents.
|
|
88
|
+
|
|
89
|
+
Interactive (TTY): show prompt, require explicit 'y', persist
|
|
90
|
+
`agent_rush.acknowledged_at` so we never ask the same machine twice.
|
|
91
|
+
|
|
92
|
+
Non-interactive (no TTY — typical when an agent runs the CLI): surface
|
|
93
|
+
the warning to stderr for the human reading the agent transcript and
|
|
94
|
+
proceed without prompting (agents can't answer y/N).
|
|
95
|
+
"""
|
|
96
|
+
config = load_config()
|
|
97
|
+
if config.agent_rush.acknowledged_at:
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
is_tty = sys.stdin.isatty() and sys.stdout.isatty()
|
|
101
|
+
if not is_tty:
|
|
102
|
+
for line in _PII_WARNING_LINES:
|
|
103
|
+
err_console.print(line)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
for line in _PII_WARNING_LINES:
|
|
107
|
+
console.print(line)
|
|
108
|
+
answer = typer.prompt(" Continue? [y/N]", default="N", show_default=False).strip().lower()
|
|
109
|
+
if answer not in ("y", "yes"):
|
|
110
|
+
print_error(err_console, "Aborted.")
|
|
111
|
+
raise typer.Exit(1)
|
|
112
|
+
|
|
113
|
+
config.agent_rush.acknowledged_at = datetime.now(timezone.utc).isoformat()
|
|
114
|
+
save_config(config)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def run_agent_rush_add(content: str) -> None:
|
|
118
|
+
_ensure_warning_acknowledged()
|
|
119
|
+
result = _call("/v1/agent-rush/memories/", {"content": content})
|
|
120
|
+
event_id = result.get("event_id", "?")
|
|
121
|
+
print_success(console, f"Memory submitted (event_id: {event_id})")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def run_agent_rush_search(query: str) -> None:
|
|
125
|
+
result = _call("/v1/agent-rush/memories/search/", {"query": query})
|
|
126
|
+
memories = result.get("results") or result.get("memories") or []
|
|
127
|
+
if not memories:
|
|
128
|
+
console.print("[dim](no results)[/dim]")
|
|
129
|
+
return
|
|
130
|
+
for i, m in enumerate(memories[:5], start=1):
|
|
131
|
+
text = m.get("memory") if isinstance(m, dict) else str(m)
|
|
132
|
+
console.print(f" {i}. {text}")
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""mem0 whoami — print the active agent's default_user_id (AGENTRUSH identifier)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
from mem0_cli.branding import BRAND_COLOR, print_error, print_info
|
|
9
|
+
from mem0_cli.config import load_config
|
|
10
|
+
|
|
11
|
+
console = Console()
|
|
12
|
+
err_console = Console(stderr=True)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def run_whoami() -> None:
|
|
16
|
+
config = load_config()
|
|
17
|
+
session_id = config.platform.default_user_id if config.platform else None
|
|
18
|
+
if not session_id:
|
|
19
|
+
print_error(
|
|
20
|
+
err_console,
|
|
21
|
+
"No default_user_id found. Run `mem0 init --agent` first.",
|
|
22
|
+
)
|
|
23
|
+
raise typer.Exit(1)
|
|
24
|
+
console.print(f"Your AGENTRUSH identifier: [{BRAND_COLOR}]{session_id}[/{BRAND_COLOR}]")
|
|
25
|
+
print_info(console, "Find your row at https://mem0.ai/agentrush")
|
|
@@ -51,12 +51,20 @@ class TelemetryConfig:
|
|
|
51
51
|
anonymous_id: str = ""
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
@dataclass
|
|
55
|
+
class AgentRushConfig:
|
|
56
|
+
# ISO timestamp the human acknowledged the "memories are public" warning.
|
|
57
|
+
# Empty until first interactive `mem0 agent-rush add`.
|
|
58
|
+
acknowledged_at: str = ""
|
|
59
|
+
|
|
60
|
+
|
|
54
61
|
@dataclass
|
|
55
62
|
class Mem0Config:
|
|
56
63
|
version: int = CONFIG_VERSION
|
|
57
64
|
defaults: DefaultsConfig = field(default_factory=DefaultsConfig)
|
|
58
65
|
platform: PlatformConfig = field(default_factory=PlatformConfig)
|
|
59
66
|
telemetry: TelemetryConfig = field(default_factory=TelemetryConfig)
|
|
67
|
+
agent_rush: AgentRushConfig = field(default_factory=AgentRushConfig)
|
|
60
68
|
|
|
61
69
|
|
|
62
70
|
SHORT_KEY_ALIASES: dict[str, str] = {
|
|
@@ -105,6 +113,9 @@ def load_config() -> Mem0Config:
|
|
|
105
113
|
telemetry = data.get("telemetry", {})
|
|
106
114
|
config.telemetry.anonymous_id = telemetry.get("anonymous_id", "")
|
|
107
115
|
|
|
116
|
+
agent_rush = data.get("agent_rush", {})
|
|
117
|
+
config.agent_rush.acknowledged_at = agent_rush.get("acknowledged_at", "")
|
|
118
|
+
|
|
108
119
|
# Environment variable overrides
|
|
109
120
|
env_key = os.environ.get("MEM0_API_KEY")
|
|
110
121
|
if env_key:
|
|
@@ -158,6 +169,9 @@ def save_config(config: Mem0Config) -> None:
|
|
|
158
169
|
"telemetry": {
|
|
159
170
|
"anonymous_id": config.telemetry.anonymous_id,
|
|
160
171
|
},
|
|
172
|
+
"agent_rush": {
|
|
173
|
+
"acknowledged_at": config.agent_rush.acknowledged_at,
|
|
174
|
+
},
|
|
161
175
|
}
|
|
162
176
|
|
|
163
177
|
with open(CONFIG_FILE, "w") as f:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|