fix(mem0-agent): detached hooks lost their payload, so nothing was ever written
Observed live: real sessions flagged durable candidates (a preference, two insights, a convention) but every session showed 'flush events: 0'. The manifest backgrounded flush and assist-error with '( cmd &)', so the parent exited and closed stdin before the child could read it -- the child then had no session_id, fell back to 'no-session', and drained an empty buffer. Now the CLI reads the payload itself and re-execs a detached worker with start_new_session, so the hook still returns in ~0.27s. Verified end to end: sent=1, session_state=created. Also records a surface hint per event and shows it in 'sessions', since the manifest pins MEM0_EDITOR to the same value on every client. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
10b8fc4bed
commit
1ea8c2e5fe
@@ -13,6 +13,8 @@ from mem0_agent.settings import SessionState, Settings
|
||||
class Args:
|
||||
def __init__(self, **kw):
|
||||
self.session_id = "sess-cli"
|
||||
self.worker = True # tests exercise the worker path directly
|
||||
self.payload_file = None
|
||||
for k, v in kw.items():
|
||||
setattr(self, k, v)
|
||||
|
||||
|
||||
@@ -106,11 +106,18 @@ def test_user_prompt_submit_is_declared_local_only(spec, manifest):
|
||||
assert entry["background"] is False and entry["blocking"] is True
|
||||
|
||||
|
||||
def test_flush_and_assist_hooks_are_detached(spec, manifest):
|
||||
def test_write_hooks_are_not_shell_backgrounded(spec, manifest):
|
||||
"""These hooks must NOT be wrapped in `( ... &)`.
|
||||
|
||||
A shell-backgrounded hook loses stdin the instant the parent exits, so the child
|
||||
sees no session_id and no transcript_path and drains the wrong buffer -- observed
|
||||
live as flagged candidates that were never written. The CLI now reads the payload
|
||||
first and re-execs itself detached, so the hook still returns in milliseconds.
|
||||
"""
|
||||
for event in ("PostToolUse", "Stop", "PreCompact", "SessionEnd"):
|
||||
command = manifest["hooks"][event][0]["hooks"][0]["command"]
|
||||
assert command.startswith("(") and command.endswith("&)"), event
|
||||
assert ">/dev/null" in command, event
|
||||
assert not command.strip().endswith("&)"), f"{event} must not be backgrounded by the shell"
|
||||
assert "mem0-agent" in command, event
|
||||
|
||||
|
||||
def test_editor_env_is_pinned(manifest):
|
||||
|
||||
Reference in New Issue
Block a user