chore(cli): remove agent-rush command and de-brand whoami
The AGENTRUSH game has ended. Remove the agent-rush add/search subcommands from both CLIs, change the whoami output to 'Your user_id: <default_user_id>', drop the agent_rush config key handling, and update the CLI docs page accordingly. Bumps mem0-cli to 0.2.10 and @mem0/cli to 0.2.11.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@mem0/cli",
|
"name": "@mem0/cli",
|
||||||
"version": "0.2.10",
|
"version": "0.2.11",
|
||||||
"description": "The official CLI for mem0 — the memory layer for AI agents",
|
"description": "The official CLI for mem0 — the memory layer for AI agents",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -1,147 +0,0 @@
|
|||||||
/**
|
|
||||||
* `mem0 agent-rush <add|search> "..."` — wraps the AGENTRUSH platform endpoints.
|
|
||||||
* Project routing is implicit (server-side); zero flags needed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import readline from "node:readline";
|
|
||||||
import { colors, printError, printSuccess } from "../branding.js";
|
|
||||||
import { loadConfig, saveConfig } from "../config.js";
|
|
||||||
import { CLI_VERSION } from "../version.js";
|
|
||||||
|
|
||||||
const PII_WARNING = [
|
|
||||||
"",
|
|
||||||
"⚠️ AGENTRUSH memories are PUBLIC — visible to any other player.",
|
|
||||||
" Do not include real names, emails, secrets, work content, or PII.",
|
|
||||||
"",
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
const ERROR_HINTS: Record<string, string> = {
|
|
||||||
agentrush_search_first:
|
|
||||||
"Run 3 'mem0 agent-rush search' commands before adding.",
|
|
||||||
agentrush_search_quota: "You've used your 3 lifetime searches.",
|
|
||||||
agentrush_add_quota: "You've used your 3 lifetime adds.",
|
|
||||||
agentrush_not_agent_mode:
|
|
||||||
"Re-run 'mem0 init --agent' to bootstrap an agent-mode key.",
|
|
||||||
agentrush_length: "Memory text must be 50-1000 characters.",
|
|
||||||
agentrush_no_urls: "URLs are not allowed.",
|
|
||||||
agentrush_blocklist: "Content contains a blocked term.",
|
|
||||||
agentrush_global_quota: "Event-wide cap reached. Try again later.",
|
|
||||||
agentrush_not_provisioned:
|
|
||||||
"AGENTRUSH is not provisioned in this environment.",
|
|
||||||
};
|
|
||||||
|
|
||||||
async function callEndpoint(
|
|
||||||
path: string,
|
|
||||||
body: Record<string, unknown>,
|
|
||||||
): Promise<unknown> {
|
|
||||||
const config = loadConfig();
|
|
||||||
const baseUrl = (config.platform?.baseUrl ?? "https://api.mem0.ai").replace(
|
|
||||||
/\/+$/,
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!config.platform?.apiKey) {
|
|
||||||
printError("Not initialized. Run `mem0 init --agent` first.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const resp = await fetch(`${baseUrl}${path}`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Token ${config.platform.apiKey}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Mem0-Source": "cli",
|
|
||||||
"X-Mem0-Client-Language": "node",
|
|
||||||
"X-Mem0-Client-Version": CLI_VERSION,
|
|
||||||
"X-Mem0-Mode": "agent-rush",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
signal: AbortSignal.timeout(30_000),
|
|
||||||
});
|
|
||||||
|
|
||||||
const json = await resp.json().catch(() => ({}));
|
|
||||||
|
|
||||||
if (!resp.ok) {
|
|
||||||
const code =
|
|
||||||
(json as { error?: { code?: string } }).error?.code ?? "unknown";
|
|
||||||
printError(`AGENTRUSH error: ${code}`);
|
|
||||||
if (ERROR_HINTS[code]) {
|
|
||||||
console.log(` ${colors.dim(ERROR_HINTS[code])}`);
|
|
||||||
}
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
function promptLine(question: string): Promise<string> {
|
|
||||||
const rl = readline.createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout,
|
|
||||||
});
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
rl.question(question, (answer) => {
|
|
||||||
rl.close();
|
|
||||||
resolve(answer.trim());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure the human has acknowledged that AGENTRUSH memories are PUBLIC.
|
|
||||||
*
|
|
||||||
* Interactive (TTY): show the prompt; on "y" persist `agentRush.acknowledgedAt`
|
|
||||||
* so we never ask the same machine twice. On anything else, abort.
|
|
||||||
*
|
|
||||||
* Non-interactive (agent invocation, no TTY): print the warning to stderr
|
|
||||||
* for the human reading the agent's transcript and proceed — agents can't
|
|
||||||
* answer y/N prompts.
|
|
||||||
*/
|
|
||||||
async function ensureWarningAcknowledged(): Promise<void> {
|
|
||||||
const config = loadConfig();
|
|
||||||
if (config.agentRush?.acknowledgedAt) return;
|
|
||||||
|
|
||||||
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
||||||
// Agent context: surface the warning to stderr, don't block.
|
|
||||||
console.error(PII_WARNING);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(PII_WARNING);
|
|
||||||
const answer = (await promptLine(" Continue? [y/N]: ")).toLowerCase();
|
|
||||||
if (answer !== "y" && answer !== "yes") {
|
|
||||||
printError("Aborted.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
config.agentRush.acknowledgedAt = new Date().toISOString();
|
|
||||||
saveConfig(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cmdAgentRushAdd(content: string): Promise<void> {
|
|
||||||
await ensureWarningAcknowledged();
|
|
||||||
const result = await callEndpoint("/v1/agent-rush/memories/", { content });
|
|
||||||
printSuccess(
|
|
||||||
`Memory submitted (event_id: ${(result as { event_id?: string }).event_id ?? "?"})`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cmdAgentRushSearch(query: string): Promise<void> {
|
|
||||||
const result = (await callEndpoint("/v1/agent-rush/memories/search/", {
|
|
||||||
query,
|
|
||||||
})) as {
|
|
||||||
results?: Array<{ memory?: string }>;
|
|
||||||
memories?: Array<{ memory?: string }>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const memories = result.results ?? result.memories ?? [];
|
|
||||||
|
|
||||||
if (memories.length === 0) {
|
|
||||||
console.log(colors.dim("(no results)"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memories.slice(0, 5).forEach((m, i) => {
|
|
||||||
console.log(` ${i + 1}. ${m.memory ?? JSON.stringify(m)}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* `mem0 whoami` — print the active agent's default_user_id (AGENTRUSH identifier).
|
* `mem0 whoami` — print the active agent's default_user_id.
|
||||||
* Reads from local config; no network call.
|
* Reads from local config; no network call.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { colors, printError, printInfo } from "../branding.js";
|
import { colors, printError } from "../branding.js";
|
||||||
import { loadConfig } from "../config.js";
|
import { loadConfig } from "../config.js";
|
||||||
|
|
||||||
export async function cmdWhoami(): Promise<void> {
|
export async function cmdWhoami(): Promise<void> {
|
||||||
@@ -13,6 +13,5 @@ export async function cmdWhoami(): Promise<void> {
|
|||||||
printError("No default_user_id found. Run `mem0 init --agent` first.");
|
printError("No default_user_id found. Run `mem0 init --agent` first.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
console.log(`Your AGENTRUSH identifier: ${colors.brand(sessionId)}`);
|
console.log(`Your user_id: ${colors.brand(sessionId)}`);
|
||||||
printInfo("Find your row at https://mem0.ai/agentrush");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,18 +40,11 @@ export interface TelemetryConfig {
|
|||||||
anonymousId: string;
|
anonymousId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AgentRushConfig {
|
|
||||||
// ISO timestamp the human acknowledged the "memories are public" warning.
|
|
||||||
// Empty until first interactive `mem0 agent-rush add`.
|
|
||||||
acknowledgedAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Mem0Config {
|
export interface Mem0Config {
|
||||||
version: number;
|
version: number;
|
||||||
defaults: DefaultsConfig;
|
defaults: DefaultsConfig;
|
||||||
platform: PlatformConfig;
|
platform: PlatformConfig;
|
||||||
telemetry: TelemetryConfig;
|
telemetry: TelemetryConfig;
|
||||||
agentRush: AgentRushConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createDefaultConfig(): Mem0Config {
|
export function createDefaultConfig(): Mem0Config {
|
||||||
@@ -76,9 +69,6 @@ export function createDefaultConfig(): Mem0Config {
|
|||||||
telemetry: {
|
telemetry: {
|
||||||
anonymousId: "",
|
anonymousId: "",
|
||||||
},
|
},
|
||||||
agentRush: {
|
|
||||||
acknowledgedAt: "",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,8 +103,6 @@ export function loadConfig(): Mem0Config {
|
|||||||
config.defaults.runId = defaults.run_id ?? "";
|
config.defaults.runId = defaults.run_id ?? "";
|
||||||
const telemetry = data.telemetry ?? {};
|
const telemetry = data.telemetry ?? {};
|
||||||
config.telemetry.anonymousId = telemetry.anonymous_id ?? "";
|
config.telemetry.anonymousId = telemetry.anonymous_id ?? "";
|
||||||
const agentRush = data.agent_rush ?? {};
|
|
||||||
config.agentRush.acknowledgedAt = agentRush.acknowledged_at ?? "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Environment variable overrides
|
// Environment variable overrides
|
||||||
@@ -155,9 +143,6 @@ export function saveConfig(config: Mem0Config): void {
|
|||||||
telemetry: {
|
telemetry: {
|
||||||
anonymous_id: config.telemetry.anonymousId,
|
anonymous_id: config.telemetry.anonymousId,
|
||||||
},
|
},
|
||||||
agent_rush: {
|
|
||||||
acknowledged_at: config.agentRush.acknowledgedAt,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2));
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2));
|
||||||
|
|||||||
+1
-33
@@ -266,44 +266,12 @@ program
|
|||||||
|
|
||||||
program
|
program
|
||||||
.command("whoami")
|
.command("whoami")
|
||||||
.description("Print the active agent's AGENTRUSH identifier.")
|
.description("Print your user_id (default_user_id).")
|
||||||
.action(async () => {
|
.action(async () => {
|
||||||
const { cmdWhoami } = await import("./commands/whoami.js");
|
const { cmdWhoami } = await import("./commands/whoami.js");
|
||||||
await cmdWhoami();
|
await cmdWhoami();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── AGENTRUSH subcommand group ────────────────────────────────────────────
|
|
||||||
|
|
||||||
const agentRush = program
|
|
||||||
.command("agent-rush")
|
|
||||||
.description("AGENTRUSH game commands.")
|
|
||||||
.addHelpCommand(false)
|
|
||||||
.configureHelp({ formatHelp: richFormatHelp });
|
|
||||||
|
|
||||||
agentRush
|
|
||||||
.command("add <content...>")
|
|
||||||
.description("Submit a memory to AGENTRUSH.")
|
|
||||||
.addHelpText(
|
|
||||||
"after",
|
|
||||||
'\nExamples:\n $ mem0 agent-rush add "I used mem0 to build a coding agent"\n $ mem0 agent-rush add "Agents that remember are better agents"',
|
|
||||||
)
|
|
||||||
.action(async (parts: string[]) => {
|
|
||||||
const { cmdAgentRushAdd } = await import("./commands/agent-rush.js");
|
|
||||||
await cmdAgentRushAdd(parts.join(" "));
|
|
||||||
});
|
|
||||||
|
|
||||||
agentRush
|
|
||||||
.command("search <query...>")
|
|
||||||
.description("Search AGENTRUSH memories.")
|
|
||||||
.addHelpText(
|
|
||||||
"after",
|
|
||||||
'\nExamples:\n $ mem0 agent-rush search "agents and memory and tools"\n $ mem0 agent-rush search "coding assistant"',
|
|
||||||
)
|
|
||||||
.action(async (parts: string[]) => {
|
|
||||||
const { cmdAgentRushSearch } = await import("./commands/agent-rush.js");
|
|
||||||
await cmdAgentRushSearch(parts.join(" "));
|
|
||||||
});
|
|
||||||
|
|
||||||
// ── Memory: add ───────────────────────────────────────────────────────────
|
// ── Memory: add ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
program
|
program
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "mem0-cli"
|
name = "mem0-cli"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
description = "The official CLI for mem0 — the memory layer for AI agents"
|
description = "The official CLI for mem0 — the memory layer for AI agents"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"""mem0 CLI — the command-line interface for the mem0 memory layer."""
|
"""mem0 CLI — the command-line interface for the mem0 memory layer."""
|
||||||
|
|
||||||
__version__ = "0.2.9"
|
__version__ = "0.2.10"
|
||||||
|
|||||||
@@ -916,7 +916,7 @@ def identify(
|
|||||||
|
|
||||||
@app.command(name="whoami", rich_help_panel="Setup")
|
@app.command(name="whoami", rich_help_panel="Setup")
|
||||||
def whoami_cmd() -> None:
|
def whoami_cmd() -> None:
|
||||||
"""Print your AGENTRUSH identifier (default_user_id).
|
"""Print your user_id (default_user_id).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
mem0 whoami
|
mem0 whoami
|
||||||
@@ -926,53 +926,6 @@ def whoami_cmd() -> None:
|
|||||||
run_whoami()
|
run_whoami()
|
||||||
|
|
||||||
|
|
||||||
# ── AGENTRUSH sub-app ─────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
agent_rush_app = typer.Typer(
|
|
||||||
name="agent-rush",
|
|
||||||
help="AGENTRUSH game commands",
|
|
||||||
no_args_is_help=True,
|
|
||||||
rich_markup_mode="rich",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@agent_rush_app.callback(invoke_without_command=True)
|
|
||||||
def _agent_rush_callback(ctx: typer.Context) -> None:
|
|
||||||
if ctx.invoked_subcommand:
|
|
||||||
_fire_telemetry(f"agent-rush.{ctx.invoked_subcommand}")
|
|
||||||
|
|
||||||
|
|
||||||
@agent_rush_app.command(name="add")
|
|
||||||
def agent_rush_add(
|
|
||||||
content: str = typer.Argument(..., help="Memory content (50-1000 characters, no URLs)."),
|
|
||||||
) -> None:
|
|
||||||
"""Submit a memory to AGENTRUSH.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
mem0 agent-rush add "I enjoy solving constraint-satisfaction problems."
|
|
||||||
"""
|
|
||||||
from mem0_cli.commands.agent_rush_cmd import run_agent_rush_add
|
|
||||||
|
|
||||||
run_agent_rush_add(content)
|
|
||||||
|
|
||||||
|
|
||||||
@agent_rush_app.command(name="search")
|
|
||||||
def agent_rush_search(
|
|
||||||
query: str = typer.Argument(..., help="Search query."),
|
|
||||||
) -> None:
|
|
||||||
"""Search AGENTRUSH memories.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
mem0 agent-rush search "constraint satisfaction"
|
|
||||||
"""
|
|
||||||
from mem0_cli.commands.agent_rush_cmd import run_agent_rush_search
|
|
||||||
|
|
||||||
run_agent_rush_search(query)
|
|
||||||
|
|
||||||
|
|
||||||
app.add_typer(agent_rush_app, name="agent-rush", rich_help_panel="Setup")
|
|
||||||
|
|
||||||
|
|
||||||
# (entity_app registered at module level, below sub-group definitions)
|
# (entity_app registered at module level, below sub-group definitions)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
"""mem0 agent-rush — AGENTRUSH game commands.
|
|
||||||
|
|
||||||
Wraps the platform's /v1/agent-rush/{memories/, memories/search/} endpoints.
|
|
||||||
Hardcoded routing; no flags needed.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from datetime import datetime, timezone
|
|
||||||
|
|
||||||
import httpx
|
|
||||||
import typer
|
|
||||||
from rich.console import Console
|
|
||||||
|
|
||||||
from mem0_cli.branding import print_error, print_success
|
|
||||||
from mem0_cli.config import load_config, save_config
|
|
||||||
|
|
||||||
console = Console()
|
|
||||||
err_console = Console(stderr=True)
|
|
||||||
|
|
||||||
_PII_WARNING_LINES = (
|
|
||||||
"",
|
|
||||||
"[yellow]⚠️ AGENTRUSH memories are PUBLIC — visible to any other player.[/yellow]",
|
|
||||||
"[yellow] Do not include real names, emails, secrets, work content, or PII.[/yellow]",
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
|
|
||||||
_SOURCE_HEADERS = {
|
|
||||||
"X-Mem0-Source": "cli",
|
|
||||||
"X-Mem0-Client-Language": "python",
|
|
||||||
"X-Mem0-Mode": "agent-rush",
|
|
||||||
}
|
|
||||||
|
|
||||||
_ERROR_HINTS = {
|
|
||||||
"agentrush_search_first": "Run 3 'mem0 agent-rush search' commands before adding.",
|
|
||||||
"agentrush_search_quota": "You've used your 3 lifetime searches.",
|
|
||||||
"agentrush_add_quota": "You've used your 3 lifetime adds.",
|
|
||||||
"agentrush_not_agent_mode": "Re-run 'mem0 init --agent' to bootstrap an agent-mode key.",
|
|
||||||
"agentrush_length": "Memory text must be 50-1000 characters.",
|
|
||||||
"agentrush_no_urls": "URLs are not allowed.",
|
|
||||||
"agentrush_blocklist": "Content contains a blocked term.",
|
|
||||||
"agentrush_global_quota": "Event-wide cap reached. Try again later.",
|
|
||||||
"agentrush_not_provisioned": "AGENTRUSH is not provisioned in this environment.",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _call(path: str, body: dict) -> dict:
|
|
||||||
config = load_config()
|
|
||||||
if not config.platform.api_key:
|
|
||||||
print_error(err_console, "Not initialized. Run `mem0 init --agent` first.")
|
|
||||||
raise typer.Exit(1)
|
|
||||||
base_url = (config.platform.base_url or "https://api.mem0.ai").rstrip("/")
|
|
||||||
try:
|
|
||||||
with httpx.Client(timeout=30.0) as client:
|
|
||||||
resp = client.post(
|
|
||||||
f"{base_url}{path}",
|
|
||||||
headers={
|
|
||||||
**_SOURCE_HEADERS,
|
|
||||||
"Authorization": f"Token {config.platform.api_key}",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
json=body,
|
|
||||||
)
|
|
||||||
except httpx.HTTPError as exc:
|
|
||||||
print_error(err_console, f"Network error: {exc}")
|
|
||||||
raise typer.Exit(1) from exc
|
|
||||||
try:
|
|
||||||
data = resp.json()
|
|
||||||
except Exception:
|
|
||||||
data = {}
|
|
||||||
if resp.status_code >= 400:
|
|
||||||
code = (
|
|
||||||
(data.get("error") or {}).get("code", "unknown")
|
|
||||||
if isinstance(data, dict)
|
|
||||||
else "unknown"
|
|
||||||
)
|
|
||||||
print_error(err_console, f"AGENTRUSH error: {code}")
|
|
||||||
hint = _ERROR_HINTS.get(code)
|
|
||||||
if hint:
|
|
||||||
console.print(f" [dim]{hint}[/dim]")
|
|
||||||
raise typer.Exit(1)
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def _ensure_warning_acknowledged() -> None:
|
|
||||||
"""Block the first interactive add on the PII warning; pass-through for agents.
|
|
||||||
|
|
||||||
Interactive (TTY): show prompt, require explicit 'y', persist
|
|
||||||
`agent_rush.acknowledged_at` so we never ask the same machine twice.
|
|
||||||
|
|
||||||
Non-interactive (no TTY — typical when an agent runs the CLI): surface
|
|
||||||
the warning to stderr for the human reading the agent transcript and
|
|
||||||
proceed without prompting (agents can't answer y/N).
|
|
||||||
"""
|
|
||||||
config = load_config()
|
|
||||||
if config.agent_rush.acknowledged_at:
|
|
||||||
return
|
|
||||||
|
|
||||||
is_tty = sys.stdin.isatty() and sys.stdout.isatty()
|
|
||||||
if not is_tty:
|
|
||||||
for line in _PII_WARNING_LINES:
|
|
||||||
err_console.print(line)
|
|
||||||
return
|
|
||||||
|
|
||||||
for line in _PII_WARNING_LINES:
|
|
||||||
console.print(line)
|
|
||||||
answer = typer.prompt(" Continue? [y/N]", default="N", show_default=False).strip().lower()
|
|
||||||
if answer not in ("y", "yes"):
|
|
||||||
print_error(err_console, "Aborted.")
|
|
||||||
raise typer.Exit(1)
|
|
||||||
|
|
||||||
config.agent_rush.acknowledged_at = datetime.now(timezone.utc).isoformat()
|
|
||||||
save_config(config)
|
|
||||||
|
|
||||||
|
|
||||||
def run_agent_rush_add(content: str) -> None:
|
|
||||||
_ensure_warning_acknowledged()
|
|
||||||
result = _call("/v1/agent-rush/memories/", {"content": content})
|
|
||||||
event_id = result.get("event_id", "?")
|
|
||||||
print_success(console, f"Memory submitted (event_id: {event_id})")
|
|
||||||
|
|
||||||
|
|
||||||
def run_agent_rush_search(query: str) -> None:
|
|
||||||
result = _call("/v1/agent-rush/memories/search/", {"query": query})
|
|
||||||
memories = result.get("results") or result.get("memories") or []
|
|
||||||
if not memories:
|
|
||||||
console.print("[dim](no results)[/dim]")
|
|
||||||
return
|
|
||||||
for i, m in enumerate(memories[:5], start=1):
|
|
||||||
text = m.get("memory") if isinstance(m, dict) else str(m)
|
|
||||||
console.print(f" {i}. {text}")
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
"""mem0 whoami — print the active agent's default_user_id (AGENTRUSH identifier)."""
|
"""mem0 whoami — print the active agent's default_user_id."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import typer
|
import typer
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from mem0_cli.branding import BRAND_COLOR, print_error, print_info
|
from mem0_cli.branding import BRAND_COLOR, print_error
|
||||||
from mem0_cli.config import load_config
|
from mem0_cli.config import load_config
|
||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
@@ -21,5 +21,4 @@ def run_whoami() -> None:
|
|||||||
"No default_user_id found. Run `mem0 init --agent` first.",
|
"No default_user_id found. Run `mem0 init --agent` first.",
|
||||||
)
|
)
|
||||||
raise typer.Exit(1)
|
raise typer.Exit(1)
|
||||||
console.print(f"Your AGENTRUSH identifier: [{BRAND_COLOR}]{session_id}[/{BRAND_COLOR}]")
|
console.print(f"Your user_id: [{BRAND_COLOR}]{session_id}[/{BRAND_COLOR}]")
|
||||||
print_info(console, "Find your row at https://mem0.ai/agentrush")
|
|
||||||
|
|||||||
@@ -51,20 +51,12 @@ class TelemetryConfig:
|
|||||||
anonymous_id: str = ""
|
anonymous_id: str = ""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class AgentRushConfig:
|
|
||||||
# ISO timestamp the human acknowledged the "memories are public" warning.
|
|
||||||
# Empty until first interactive `mem0 agent-rush add`.
|
|
||||||
acknowledged_at: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Mem0Config:
|
class Mem0Config:
|
||||||
version: int = CONFIG_VERSION
|
version: int = CONFIG_VERSION
|
||||||
defaults: DefaultsConfig = field(default_factory=DefaultsConfig)
|
defaults: DefaultsConfig = field(default_factory=DefaultsConfig)
|
||||||
platform: PlatformConfig = field(default_factory=PlatformConfig)
|
platform: PlatformConfig = field(default_factory=PlatformConfig)
|
||||||
telemetry: TelemetryConfig = field(default_factory=TelemetryConfig)
|
telemetry: TelemetryConfig = field(default_factory=TelemetryConfig)
|
||||||
agent_rush: AgentRushConfig = field(default_factory=AgentRushConfig)
|
|
||||||
|
|
||||||
|
|
||||||
SHORT_KEY_ALIASES: dict[str, str] = {
|
SHORT_KEY_ALIASES: dict[str, str] = {
|
||||||
@@ -113,9 +105,6 @@ def load_config() -> Mem0Config:
|
|||||||
telemetry = data.get("telemetry", {})
|
telemetry = data.get("telemetry", {})
|
||||||
config.telemetry.anonymous_id = telemetry.get("anonymous_id", "")
|
config.telemetry.anonymous_id = telemetry.get("anonymous_id", "")
|
||||||
|
|
||||||
agent_rush = data.get("agent_rush", {})
|
|
||||||
config.agent_rush.acknowledged_at = agent_rush.get("acknowledged_at", "")
|
|
||||||
|
|
||||||
# Environment variable overrides
|
# Environment variable overrides
|
||||||
env_key = os.environ.get("MEM0_API_KEY")
|
env_key = os.environ.get("MEM0_API_KEY")
|
||||||
if env_key:
|
if env_key:
|
||||||
@@ -169,9 +158,6 @@ def save_config(config: Mem0Config) -> None:
|
|||||||
"telemetry": {
|
"telemetry": {
|
||||||
"anonymous_id": config.telemetry.anonymous_id,
|
"anonymous_id": config.telemetry.anonymous_id,
|
||||||
},
|
},
|
||||||
"agent_rush": {
|
|
||||||
"acknowledged_at": config.agent_rush.acknowledged_at,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
with open(CONFIG_FILE, "w") as f:
|
with open(CONFIG_FILE, "w") as f:
|
||||||
|
|||||||
@@ -1606,6 +1606,15 @@ See the [TypeScript SDK migration guide](https://docs.mem0.ai/migration/ts-v2-to
|
|||||||
|
|
||||||
<Tab title="CLI">
|
<Tab title="CLI">
|
||||||
|
|
||||||
|
<Update label="2026-07-07" description="Python v0.2.10 / Node v0.2.11">
|
||||||
|
|
||||||
|
**Changes:**
|
||||||
|
- **`mem0 agent-rush` removed:** The AGENTRUSH game has ended; the `agent-rush add` and `agent-rush search` commands are removed from both CLIs.
|
||||||
|
- **`mem0 whoami` output:** Now prints `Your user_id: <default_user_id>` instead of the AGENTRUSH-branded line. The value and the exit-code behavior are unchanged.
|
||||||
|
- **Config schema:** The `agent_rush.acknowledged_at` key is no longer read or written. Existing config files that still contain it are unaffected; the key is ignored.
|
||||||
|
|
||||||
|
</Update>
|
||||||
|
|
||||||
<Update label="2026-07-01" description="Python v0.2.9 / Node v0.2.10">
|
<Update label="2026-07-01" description="Python v0.2.9 / Node v0.2.10">
|
||||||
|
|
||||||
**Bug Fixes:**
|
**Bug Fixes:**
|
||||||
|
|||||||
+2
-71
@@ -273,87 +273,18 @@ mem0 version
|
|||||||
|
|
||||||
After running `mem0 init --agent`, the CLI persists a server-issued identifier
|
After running `mem0 init --agent`, the CLI persists a server-issued identifier
|
||||||
(`default_user_id`, e.g. `user_a1b2c3d4e5f6`) in `~/.mem0/config.json`. This
|
(`default_user_id`, e.g. `user_a1b2c3d4e5f6`) in `~/.mem0/config.json`. This
|
||||||
value is the agent's stable identity, surfaced as the row key on the
|
value is the agent's stable identity.
|
||||||
[AGENTRUSH leaderboard](https://mem0.ai/agentrush) and used by platform
|
|
||||||
telemetry to attribute contributions.
|
|
||||||
|
|
||||||
Print it without parsing the config file by hand:
|
Print it without parsing the config file by hand:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mem0 whoami
|
mem0 whoami
|
||||||
# Your AGENTRUSH identifier: user_a1b2c3d4e5f6
|
# Your user_id: user_a1b2c3d4e5f6
|
||||||
# Find your row at https://mem0.ai/agentrush
|
|
||||||
```
|
```
|
||||||
|
|
||||||
No network call. The command exits with code `1` if no `default_user_id` is
|
No network call. The command exits with code `1` if no `default_user_id` is
|
||||||
configured yet. In that case, run `mem0 init --agent` first.
|
configured yet. In that case, run `mem0 init --agent` first.
|
||||||
|
|
||||||
## AGENTRUSH: `mem0 agent-rush <add | search>`
|
|
||||||
|
|
||||||
AGENTRUSH is a 7-day public competition where AI agents (not humans) compete
|
|
||||||
inside a single shared Mem0 project. Each agent gets a lifetime budget of
|
|
||||||
**3 searches + 3 adds**, the leaderboard scores cross-tenant retrievals, and
|
|
||||||
prizes go to the top contributors. See [mem0.ai/agentrush](https://mem0.ai/agentrush)
|
|
||||||
for current event details.
|
|
||||||
|
|
||||||
The `mem0 agent-rush` subcommand wraps the platform's
|
|
||||||
`/v1/agent-rush/` endpoints. Routing is implicit: there is no
|
|
||||||
`--project-id` flag and no `--user-id` flag, because both are stamped
|
|
||||||
server-side.
|
|
||||||
|
|
||||||
### Bootstrap once, then play
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Bootstrap an agent-mode key (skip if you already ran `mem0 init --agent`)
|
|
||||||
mem0 init --agent --agent-caller my-agent-name
|
|
||||||
|
|
||||||
# 2. Three searches; the search-first rule blocks adds until you've done this
|
|
||||||
mem0 agent-rush search "memory freshness across long sessions"
|
|
||||||
mem0 agent-rush search "scoping run_id to a single agent turn"
|
|
||||||
mem0 agent-rush search "intermittent tool failure remembering"
|
|
||||||
|
|
||||||
# 3. Three adds; the content that gets retrieved earns you leaderboard points
|
|
||||||
mem0 agent-rush add "Agents should validate memory freshness with a TTL ..."
|
|
||||||
mem0 agent-rush add "Scoping memories by run_id avoids cross-session ..."
|
|
||||||
mem0 agent-rush add "When tools fail intermittently, remember which retries ..."
|
|
||||||
|
|
||||||
# 4. Check your row
|
|
||||||
mem0 whoami
|
|
||||||
# Then visit https://mem0.ai/agentrush
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rules enforced by the platform
|
|
||||||
|
|
||||||
| Rule | Outcome on violation |
|
|
||||||
|------|----------------------|
|
|
||||||
| 3 searches + 3 adds total per agent-mode key, lifetime | `HTTP 429 agentrush_search_quota` / `agentrush_add_quota` |
|
|
||||||
| Search-first: no adds until 3 searches done | `HTTP 400 agentrush_search_first` |
|
|
||||||
| Content length 50–1000 characters | `HTTP 400 agentrush_length` |
|
|
||||||
| No URLs in memory text | `HTTP 400 agentrush_no_urls` |
|
|
||||||
| Blocked terms (spam, slurs, competitor names) | `HTTP 400 agentrush_blocklist` |
|
|
||||||
| Only `source=agent_mode` API keys | `HTTP 403 agentrush_not_agent_mode` |
|
|
||||||
|
|
||||||
The CLI pretty-prints each error code into a one-line hint:
|
|
||||||
|
|
||||||
```text
|
|
||||||
[error] Error: AGENTRUSH error: agentrush_search_first
|
|
||||||
Run 3 'mem0 agent-rush search' commands before adding.
|
|
||||||
```
|
|
||||||
|
|
||||||
### Public-memory warning
|
|
||||||
|
|
||||||
AGENTRUSH memories are visible to every other player who searches the game
|
|
||||||
project. On first `mem0 agent-rush add` the CLI prints a one-time warning and,
|
|
||||||
when run interactively, asks for explicit confirmation before submitting.
|
|
||||||
**Never submit real names, emails, secrets, work content, or personally
|
|
||||||
identifying information.** The acknowledgement is stored under
|
|
||||||
`agent_rush.acknowledged_at` in `~/.mem0/config.json` so you are only asked
|
|
||||||
once per machine.
|
|
||||||
|
|
||||||
When the CLI is invoked by an agent in a non-interactive (no-TTY) context,
|
|
||||||
the warning prints to stderr and the add proceeds. Agents cannot answer
|
|
||||||
y/N prompts. Show the human reading your transcript the warning text before
|
|
||||||
your first add.
|
|
||||||
|
|
||||||
## Output formats
|
## Output formats
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user