fix(cli): JSON error envelope shows command name + clearer rate-limit message
Two papercuts surfaced when prod's bootstrap returned 403:
{"status": "error", "command": "", "error": "Bootstrap failed: {\"detail\":\"You do not have permission to perform this action.\"}", "data": null}
1. `"command": ""` — the JSON error envelope (printError under agent
mode) reads from current_command state, but nothing ever called
setCurrentCommand on the init subcommand. Hook into Node's
preAction and Python's main_callback to stash the active
subcommand name so error envelopes report which command failed.
2. Opaque rate-limit message. The backend's @ratelimit decorator
raises PermissionDenied → DRF translates to generic 403
"You do not have permission to perform this action." Users don't
know it's a rate limit. Detect status_code==403 with /permission/i
in the detail and surface the actual reason:
"Daily Agent Mode signup limit reached for this network (5/day).
Try again from a different IP or after midnight UTC."
Both fixes mirrored in Python (agent_mode_cmd.py, app.py) and Node
(agent-mode.ts, index.ts).
This commit is contained in:
@@ -236,6 +236,13 @@ def main_callback(
|
||||
_fire_telemetry("version")
|
||||
cmd_version()
|
||||
raise typer.Exit()
|
||||
if ctx.invoked_subcommand:
|
||||
# Stash the active subcommand name so the JSON error envelope
|
||||
# (print_error in agent mode) can report which command failed
|
||||
# instead of an empty `"command": ""` field.
|
||||
from mem0_cli.state import set_current_command
|
||||
|
||||
set_current_command(ctx.invoked_subcommand)
|
||||
if ctx.invoked_subcommand and ctx.invoked_subcommand != "init":
|
||||
# init fires its own telemetry from init_cmd.run_init with full M1-M6 props.
|
||||
_fire_telemetry(ctx.invoked_subcommand)
|
||||
|
||||
@@ -61,10 +61,21 @@ def bootstrap_via_backend(
|
||||
print_error(err_console, "Agent Mode is temporarily disabled. Try again later.")
|
||||
raise typer.Exit(1)
|
||||
if resp.status_code != 200:
|
||||
detail = resp.text
|
||||
try:
|
||||
detail = resp.json().get("error", resp.text)
|
||||
body = resp.json()
|
||||
detail = body.get("error") or body.get("detail") or resp.text
|
||||
except Exception:
|
||||
detail = resp.text
|
||||
pass
|
||||
# Backend's @ratelimit decorator raises PermissionDenied, which DRF
|
||||
# translates to a generic 403 "You do not have permission to perform
|
||||
# this action." That's opaque — surface as the rate-limit it actually is.
|
||||
if resp.status_code == 403 and "permission" in str(detail).lower():
|
||||
print_error(
|
||||
err_console,
|
||||
"Daily Agent Mode signup limit reached for this network (5/day). Try again from a different IP or after midnight UTC.",
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
print_error(err_console, f"Bootstrap failed: {detail}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user