Skip to content

Commit ffedcad

Browse files
committed
Clean up some client handling of user IDs
1 parent 4f26734 commit ffedcad

File tree

7 files changed

+54
-61
lines changed

7 files changed

+54
-61
lines changed

agent-memory-client/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ await client.update_working_memory_data(
206206

207207
# Append messages
208208
new_messages = [
209-
MemoryMessage(role="user", content="What's the weather?"),
210-
MemoryMessage(role="assistant", content="It's sunny today!")
209+
{"role": "user", "content": "What's the weather?"},
210+
{"role": "assistant", "content": "It's sunny today!"}
211211
]
212212

213213
await client.append_messages_to_working_memory(

agent-memory-client/agent_memory_client/client.py

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ async def get_working_memory(
233233
"""
234234
params = {}
235235

236+
if user_id is not None:
237+
params["user_id"] = user_id
238+
236239
if namespace is not None:
237240
params["namespace"] = namespace
238241
elif self.config.default_namespace is not None:
@@ -258,7 +261,12 @@ async def get_working_memory(
258261
f"/v1/working-memory/{session_id}", params=params
259262
)
260263
response.raise_for_status()
261-
return WorkingMemoryResponse(**response.json())
264+
265+
# Get the raw JSON response
266+
response_data = response.json()
267+
268+
# Messages from JSON parsing are already in the correct dict format
269+
return WorkingMemoryResponse(**response_data)
262270
except httpx.HTTPStatusError as e:
263271
self._handle_http_error(e.response)
264272
raise
@@ -267,6 +275,7 @@ async def put_working_memory(
267275
self,
268276
session_id: str,
269277
memory: WorkingMemory,
278+
user_id: str | None = None,
270279
model_name: str | None = None,
271280
context_window_max: int | None = None,
272281
) -> WorkingMemoryResponse:
@@ -276,6 +285,7 @@ async def put_working_memory(
276285
Args:
277286
session_id: The session ID to store memory for
278287
memory: WorkingMemory object with messages and optional context
288+
user_id: Optional user ID for the session (overrides user_id in memory object)
279289
model_name: Optional model name for context window management
280290
context_window_max: Optional direct specification of context window max tokens
281291
@@ -289,6 +299,9 @@ async def put_working_memory(
289299
# Build query parameters for model-aware summarization
290300
params = {}
291301

302+
if user_id is not None:
303+
params["user_id"] = user_id
304+
292305
# Use provided model_name or fall back to config default
293306
effective_model_name = model_name or self.config.default_model_name
294307
if effective_model_name is not None:
@@ -2023,9 +2036,8 @@ async def update_working_memory_data(
20232036
async def append_messages_to_working_memory(
20242037
self,
20252038
session_id: str,
2026-
messages: list[Any], # Using Any since MemoryMessage isn't imported
2039+
messages: list[dict[str, Any]], # Expect proper message dicts
20272040
namespace: str | None = None,
2028-
auto_summarize: bool = True,
20292041
model_name: str | None = None,
20302042
context_window_max: int | None = None,
20312043
) -> WorkingMemoryResponse:
@@ -2036,9 +2048,8 @@ async def append_messages_to_working_memory(
20362048
20372049
Args:
20382050
session_id: Target session
2039-
messages: List of messages to append
2051+
messages: List of message dictionaries with 'role' and 'content' keys
20402052
namespace: Optional namespace
2041-
auto_summarize: Whether to allow automatic summarization
20422053
model_name: Optional model name for token-based summarization
20432054
context_window_max: Optional direct specification of context window max tokens
20442055
@@ -2052,48 +2063,19 @@ async def append_messages_to_working_memory(
20522063
session_id=session_id, namespace=namespace
20532064
)
20542065

2055-
# Combine messages - convert MemoryMessage objects to dicts if needed
2056-
existing_messages = existing_memory.messages if existing_memory else []
2057-
2058-
# Convert existing messages to dict format if they're objects
2059-
converted_existing_messages = []
2060-
for msg in existing_messages:
2061-
if hasattr(msg, "model_dump") and callable(
2062-
getattr(msg, "model_dump", None)
2063-
):
2064-
converted_existing_messages.append(msg.model_dump()) # type: ignore
2065-
elif (
2066-
hasattr(msg, "role")
2067-
and hasattr(msg, "content")
2068-
and not isinstance(msg, dict)
2069-
):
2070-
converted_existing_messages.append(
2071-
{"role": msg.role, "content": msg.content} # type: ignore
2072-
)
2073-
elif isinstance(msg, dict):
2074-
# Message is already a dictionary, use as-is
2075-
converted_existing_messages.append(msg)
2076-
else:
2077-
# Fallback for any other message type - convert to string content
2078-
converted_existing_messages.append(
2079-
{"role": "user", "content": str(msg)}
2066+
# Validate new messages have required structure
2067+
for msg in messages:
2068+
if not isinstance(msg, dict) or "role" not in msg or "content" not in msg:
2069+
raise ValueError(
2070+
"All messages must be dictionaries with 'role' and 'content' keys"
20802071
)
20812072

2082-
# Convert new messages to dict format if they're objects
2083-
new_messages = []
2084-
for msg in messages:
2085-
if hasattr(msg, "model_dump"):
2086-
new_messages.append(msg.model_dump())
2087-
elif hasattr(msg, "role") and hasattr(msg, "content"):
2088-
new_messages.append({"role": msg.role, "content": msg.content})
2089-
elif isinstance(msg, dict):
2090-
# Message is already a dictionary, use as-is
2091-
new_messages.append(msg)
2092-
else:
2093-
# Fallback - assume it's already in the right format
2094-
new_messages.append(msg)
2073+
# Get existing messages (already in proper dict format from get_working_memory)
2074+
existing_messages = []
2075+
if existing_memory and existing_memory.messages:
2076+
existing_messages = existing_memory.messages
20952077

2096-
final_messages = converted_existing_messages + new_messages
2078+
final_messages = existing_messages + messages
20972079

20982080
# Create updated working memory
20992081
working_memory = WorkingMemory(

agent-memory-client/tests/test_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,8 @@ async def test_append_messages_to_working_memory(self, enhanced_test_client):
527527
)
528528

529529
new_messages = [
530-
MemoryMessage(role="assistant", content="Second message"),
531-
MemoryMessage(role="user", content="Third message"),
530+
{"role": "assistant", "content": "Second message"},
531+
{"role": "user", "content": "Third message"},
532532
]
533533

534534
with (

agent_memory_server/dependencies.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,19 @@ async def add_task(
2727
logger.info("Scheduling task through Docket")
2828
# Get the Redis connection that's already configured (will use testcontainer in tests)
2929
redis_conn = await get_redis_conn()
30-
# Use the connection's URL instead of settings.redis_url directly
31-
redis_url = redis_conn.connection_pool.connection_kwargs.get(
32-
"url", settings.redis_url
33-
)
30+
31+
# Extract Redis URL from the connection pool
32+
connection_kwargs = redis_conn.connection_pool.connection_kwargs
33+
if "host" in connection_kwargs and "port" in connection_kwargs:
34+
redis_url = (
35+
f"redis://{connection_kwargs['host']}:{connection_kwargs['port']}"
36+
)
37+
if "db" in connection_kwargs:
38+
redis_url += f"/{connection_kwargs['db']}"
39+
else:
40+
# Fallback to settings if we can't extract from connection
41+
redis_url = settings.redis_url
42+
3443
logger.info("redis_url: %s", redis_url)
3544
logger.info("docket_name: %s", settings.docket_name)
3645
async with Docket(

tests/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,11 +275,11 @@ def redis_url(redis_container):
275275

276276

277277
@pytest.fixture()
278-
def async_redis_client(redis_url):
278+
def async_redis_client(use_test_redis_connection):
279279
"""
280-
An async Redis client that uses the dynamic `redis_url`.
280+
An async Redis client that uses the same connection as other test fixtures.
281281
"""
282-
return AsyncRedis.from_url(redis_url)
282+
return use_test_redis_connection
283283

284284

285285
@pytest.fixture()

tests/test_cli.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,11 @@ class TestTaskWorker:
229229

230230
@patch("docket.Worker.run")
231231
@patch("agent_memory_server.cli.settings")
232-
def test_task_worker_success(self, mock_settings, mock_worker_run):
232+
def test_task_worker_success(self, mock_settings, mock_worker_run, redis_url):
233233
"""Test successful task worker start."""
234234
mock_settings.use_docket = True
235235
mock_settings.docket_name = "test-docket"
236-
mock_settings.redis_url = "redis://localhost:6379/0"
236+
mock_settings.redis_url = redis_url
237237

238238
mock_worker_run.return_value = None
239239

@@ -258,11 +258,13 @@ def test_task_worker_docket_disabled(self, mock_settings):
258258

259259
@patch("docket.Worker.run")
260260
@patch("agent_memory_server.cli.settings")
261-
def test_task_worker_default_params(self, mock_settings, mock_worker_run):
261+
def test_task_worker_default_params(
262+
self, mock_settings, mock_worker_run, redis_url
263+
):
262264
"""Test task worker with default parameters."""
263265
mock_settings.use_docket = True
264266
mock_settings.docket_name = "test-docket"
265-
mock_settings.redis_url = "redis://localhost:6379/0"
267+
mock_settings.redis_url = redis_url
266268

267269
mock_worker_run.return_value = None
268270

tests/test_client_enhancements.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,8 @@ async def test_append_messages_to_working_memory(self, enhanced_test_client):
533533
)
534534

535535
new_messages = [
536-
MemoryMessage(role="assistant", content="Second message"),
537-
MemoryMessage(role="user", content="Third message"),
536+
{"role": "assistant", "content": "Second message"},
537+
{"role": "user", "content": "Third message"},
538538
]
539539

540540
with (

0 commit comments

Comments
 (0)