fix(mem0-agent): accept --session-id after the subcommand

The generated manifest writes 'mem0-agent context --session-id $CLAUDE_SESSION_ID',
but the flag was only on the top-level parser, so argparse rejected it and every
SessionStart hook exited 2 -- the plugin would install and silently do nothing.

Both orders now work, and a new test runs every command line in the manifest
through the parser so a manifest/CLI mismatch fails the build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Deshraj Yadav
2026-07-29 02:02:29 -07:00
parent a2ae930e9f
commit a07756f6d7
2 changed files with 60 additions and 1 deletions
+17 -1
View File
@@ -374,7 +374,23 @@ def cmd_config(args) -> int:
def main(argv: list[str] | None = None) -> int:
p = argparse.ArgumentParser(prog="mem0-agent", description="Coding-agent memory")
p.add_argument("--session-id")
sub = p.add_subparsers(dest="cmd", required=True)
# Also accepted AFTER the subcommand, which is how hook manifests naturally write it
# ("mem0-agent context --session-id X"). SUPPRESS keeps the subparser from clobbering
# a value that was given before the subcommand.
common = argparse.ArgumentParser(add_help=False)
common.add_argument("--session-id", default=argparse.SUPPRESS,
help="session identifier supplied by the editor")
_add_parser = p.add_subparsers(dest="cmd", required=True).add_parser
def add(name: str, **kw):
return _add_parser(name, parents=[common], **kw)
class _Sub:
add_parser = staticmethod(add)
sub = _Sub()
sp = sub.add_parser("setup", help="apply project configuration")
sp.set_defaults(fn=cmd_setup)
+43
View File
@@ -139,3 +139,46 @@ def test_hook_manifest_commands_all_exist():
assert sub in known, f"manifest invokes unknown subcommand {sub!r}"
found += 1
assert found >= 6
def test_session_id_accepted_on_either_side_of_the_subcommand(monkeypatch):
"""The hook manifest writes `mem0-agent context --session-id X`. argparse only
accepts a top-level flag BEFORE the subcommand, so without a per-subcommand copy
every SessionStart hook exits 2 and the plugin silently does nothing."""
seen = []
monkeypatch.setattr(cli, "cmd_context", lambda a: seen.append(getattr(a, "session_id", None)) or 0)
cli.main(["context", "--session-id", "AFTER"])
cli.main(["--session-id", "BEFORE", "context"])
assert seen == ["AFTER", "BEFORE"]
def test_every_manifest_command_parses_verbatim(monkeypatch):
"""Every command line in the generated manifest must parse.
This is the test that would have caught SessionStart exiting 2 on install:
the manifest wrote the global --session-id flag after the subcommand.
"""
import pathlib
import shlex
manifest = pathlib.Path(__file__).resolve().parents[1] / "hooks/hooks.json"
data = json.loads(manifest.read_text())
ran = []
for name in ("cmd_context", "cmd_observe", "cmd_flush", "cmd_assist_error"):
monkeypatch.setattr(cli, name, lambda a, _n=name: ran.append(_n) or 0)
checked = 0
for entries in data["hooks"].values():
for entry in entries:
for hook in entry.get("hooks", []):
raw = hook["command"].strip("() ").split(">/dev/null")[0]
tokens = shlex.split(raw)
idx = tokens.index("mem0-agent")
argv = [t for t in tokens[idx + 1:] if t != "&"]
# shell vars like "$CLAUDE_SESSION_ID" become a literal in the test
argv = ["session-x" if t.startswith("$") else t for t in argv]
assert cli.main(argv) == 0, f"manifest command did not run: {raw}"
checked += 1
assert checked >= 6
assert ran, "the manifest should invoke real subcommands"