From 5c6ca705f10514647bcb59db610342f32d6a0599 Mon Sep 17 00:00:00 2001 From: Ari Webb Date: Thu, 5 Feb 2026 11:14:08 -0800 Subject: [PATCH] Revert "feat: bring back use message packing for timezone [LET-6846]" (#9302) Revert "feat: bring back use message packing for timezone [LET-6846] (#9256)" This reverts commit c5017cccdef95b84fc585b26a0ddc5b7e44eb7c9. --- letta/helpers/message_helper.py | 5 +- letta/server/rest_api/utils.py | 6 +- letta/services/agent_manager.py | 2 +- .../services/helpers/agent_manager_helper.py | 13 +-- letta/system.py | 2 +- tests/managers/test_agent_manager.py | 103 ------------------ tests/test_client.py | 75 ------------- 7 files changed, 12 insertions(+), 194 deletions(-) diff --git a/letta/helpers/message_helper.py b/letta/helpers/message_helper.py index 2ab76833..84d8cd0b 100644 --- a/letta/helpers/message_helper.py +++ b/letta/helpers/message_helper.py @@ -1,7 +1,6 @@ import asyncio import base64 import mimetypes -from typing import Optional from urllib.parse import unquote, urlparse import httpx @@ -64,7 +63,7 @@ async def _fetch_image_from_url(url: str, max_retries: int = 1, timeout_seconds: async def convert_message_creates_to_messages( message_creates: list[MessageCreate], agent_id: str, - timezone: Optional[str], + timezone: str, run_id: str, wrap_user_message: bool = True, wrap_system_message: bool = True, @@ -87,7 +86,7 @@ async def convert_message_creates_to_messages( async def _convert_message_create_to_message( message_create: MessageCreate, agent_id: str, - timezone: Optional[str], + timezone: str, run_id: str, wrap_user_message: bool = True, wrap_system_message: bool = True, diff --git a/letta/server/rest_api/utils.py b/letta/server/rest_api/utils.py index b04402e1..66e15572 100644 --- a/letta/server/rest_api/utils.py +++ b/letta/server/rest_api/utils.py @@ -156,7 +156,7 @@ def capture_sentry_exception(e: BaseException): async def create_input_messages( - input_messages: List[MessageCreate], agent_id: str, timezone: Optional[str], run_id: str, actor: User + input_messages: List[MessageCreate], agent_id: str, timezone: str, run_id: str, actor: User ) -> List[Message]: """ Converts a user input message into the internal structured format. @@ -164,9 +164,9 @@ async def create_input_messages( TODO (cliandy): this effectively duplicates the functionality of `convert_message_creates_to_messages`, we should unify this when it's clear what message attributes we need. """ - wrap_user_message = timezone is not None + messages = await convert_message_creates_to_messages( - input_messages, agent_id, timezone, run_id, wrap_user_message=wrap_user_message, wrap_system_message=False + input_messages, agent_id, timezone, run_id, wrap_user_message=False, wrap_system_message=False ) return messages diff --git a/letta/services/agent_manager.py b/letta/services/agent_manager.py index 211cb06a..61ef77ca 100644 --- a/letta/services/agent_manager.py +++ b/letta/services/agent_manager.py @@ -521,7 +521,7 @@ class AgentManager: response_format=agent_create.response_format, created_by_id=actor.id, last_updated_by_id=actor.id, - timezone=agent_create.timezone, + timezone=agent_create.timezone if agent_create.timezone else DEFAULT_TIMEZONE, max_files_open=agent_create.max_files_open, per_file_view_window_char_limit=agent_create.per_file_view_window_char_limit, ) diff --git a/letta/services/helpers/agent_manager_helper.py b/letta/services/helpers/agent_manager_helper.py index 6554d0e8..1bcf6683 100644 --- a/letta/services/helpers/agent_manager_helper.py +++ b/letta/services/helpers/agent_manager_helper.py @@ -472,19 +472,16 @@ async def initialize_message_sequence_async( def package_initial_message_sequence( - agent_id: str, initial_message_sequence: List[MessageCreate], model: str, timezone: Optional[str], actor: User + agent_id: str, initial_message_sequence: List[MessageCreate], model: str, timezone: str, actor: User ) -> List[Message]: # create the agent object init_messages = [] for message_create in initial_message_sequence: if message_create.role == MessageRole.user: - if timezone is not None: - packed_message = system.package_user_message( - user_message=message_create.content, - timezone=timezone, - ) - else: - packed_message = message_create.content + packed_message = system.package_user_message( + user_message=message_create.content, + timezone=timezone, + ) init_messages.append( Message( role=message_create.role, diff --git a/letta/system.py b/letta/system.py index 6737e3c2..e766420b 100644 --- a/letta/system.py +++ b/letta/system.py @@ -125,7 +125,7 @@ def get_login_event(timezone, last_login="Never (first login)", include_location def package_user_message( user_message: str, - timezone: Optional[str], + timezone: str, include_location: bool = False, location_name: Optional[str] = "San Francisco, CA, USA", name: Optional[str] = None, diff --git a/tests/managers/test_agent_manager.py b/tests/managers/test_agent_manager.py index fa609f05..a1170d19 100644 --- a/tests/managers/test_agent_manager.py +++ b/tests/managers/test_agent_manager.py @@ -699,109 +699,6 @@ async def test_update_agent(server: SyncServer, comprehensive_test_agent_fixture assert updated_agent.updated_at > last_updated_timestamp -@pytest.mark.asyncio -async def test_create_agent_without_timezone_no_message_packing(server: SyncServer, default_user, default_block): - """Test that agent created without timezone has raw user messages (not JSON wrapped).""" - test_message = "hello world without timezone" - memory_blocks = [CreateBlock(label="human", value="TestUser"), CreateBlock(label="persona", value="I am a helpful assistant")] - create_agent_request = CreateAgent( - agent_type="memgpt_v2_agent", - system="test system", - memory_blocks=memory_blocks, - llm_config=LLMConfig.default_config("gpt-4o-mini"), - embedding_config=EmbeddingConfig.default_config(provider="openai"), - block_ids=[default_block.id], - initial_message_sequence=[MessageCreate(role=MessageRole.user, content=test_message)], - include_base_tools=False, - # No timezone specified - should be None - ) - agent_state = await server.agent_manager.create_agent_async( - create_agent_request, - actor=default_user, - ) - - try: - # Verify timezone is None - assert agent_state.timezone is None, f"Expected timezone to be None, got {agent_state.timezone}" - - # Get the messages - init_messages = await server.message_manager.get_messages_by_ids_async(message_ids=agent_state.message_ids, actor=default_user) - - # Find the user message - user_messages = [m for m in init_messages if m.role == MessageRole.user] - assert len(user_messages) == 1, f"Expected 1 user message, got {len(user_messages)}" - - # Check that the raw content is the plain text (not JSON wrapped) - raw_content = user_messages[0].content[0].text - assert raw_content == test_message, f"Expected raw message '{test_message}', got '{raw_content}'" - - # Verify it's NOT JSON - try: - parsed = json.loads(raw_content) - # If we get here, the content is JSON - that's wrong for no-timezone case - assert False, f"Expected raw text but got JSON: {parsed}" - except json.JSONDecodeError: - # Expected - the content should not be valid JSON - pass - finally: - await server.agent_manager.delete_agent_async(agent_id=agent_state.id, actor=default_user) - - -@pytest.mark.asyncio -async def test_create_agent_with_timezone_message_packing(server: SyncServer, default_user, default_block): - """Test that agent created with timezone has JSON wrapped user messages with timestamp.""" - test_message = "hello world with timezone" - memory_blocks = [CreateBlock(label="human", value="TestUser"), CreateBlock(label="persona", value="I am a helpful assistant")] - create_agent_request = CreateAgent( - agent_type="memgpt_v2_agent", - system="test system", - memory_blocks=memory_blocks, - llm_config=LLMConfig.default_config("gpt-4o-mini"), - embedding_config=EmbeddingConfig.default_config(provider="openai"), - block_ids=[default_block.id], - initial_message_sequence=[MessageCreate(role=MessageRole.user, content=test_message)], - include_base_tools=False, - timezone="America/Los_Angeles", - ) - agent_state = await server.agent_manager.create_agent_async( - create_agent_request, - actor=default_user, - ) - - try: - # Verify timezone is set - assert agent_state.timezone == "America/Los_Angeles", f"Expected timezone 'America/Los_Angeles', got {agent_state.timezone}" - - # Get the messages - init_messages = await server.message_manager.get_messages_by_ids_async(message_ids=agent_state.message_ids, actor=default_user) - - # Find the user message - user_messages = [m for m in init_messages if m.role == MessageRole.user] - assert len(user_messages) == 1, f"Expected 1 user message, got {len(user_messages)}" - - # Check that the raw content is JSON wrapped - raw_content = user_messages[0].content[0].text - - # Verify it IS valid JSON with expected structure - parsed = json.loads(raw_content) - assert isinstance(parsed, dict), f"Expected JSON object, got {type(parsed)}" - assert "type" in parsed, "Expected 'type' field in packed message" - assert "message" in parsed, "Expected 'message' field in packed message" - assert "time" in parsed, "Expected 'time' field in packed message" - - # Verify the inner message content - assert parsed["type"] == "user_message", f"Expected type 'user_message', got '{parsed['type']}'" - assert parsed["message"] == test_message, f"Expected inner message '{test_message}', got '{parsed['message']}'" - - # Verify the time contains timezone info (PST or PDT for America/Los_Angeles) - time_str = parsed["time"] - assert any(tz in time_str for tz in ["PST", "PDT", "-0800", "-0700"]), ( - f"Expected Pacific timezone indicator in time string '{time_str}'" - ) - finally: - await server.agent_manager.delete_agent_async(agent_id=agent_state.id, actor=default_user) - - @pytest.mark.asyncio async def test_create_agent_with_compaction_settings(server: SyncServer, default_user, default_block): """Test that agents can be created with custom compaction_settings""" diff --git a/tests/test_client.py b/tests/test_client.py index 0ee428ec..9efed475 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -790,81 +790,6 @@ def test_initial_sequence(client: Letta): # assert agent.timezone == "America/New_York" -def test_agent_timezone_none_no_message_packing(client: Letta): - """Test that agent created without timezone has timezone=None and messages are not JSON wrapped.""" - agent = client.agents.create( - memory_blocks=[{"label": "human", "value": ""}, {"label": "persona", "value": ""}], - model="anthropic/claude-haiku-4-5-20251001", - embedding="openai/text-embedding-3-small", - # No timezone specified - ) - - try: - # Verify timezone is None - retrieved_agent = client.agents.retrieve(agent_id=agent.id) - assert retrieved_agent.timezone is None, f"Expected timezone to be None, got {retrieved_agent.timezone}" - - # Send a message - test_message = "Hello, this is a test message without timezone" - client.agents.messages.create( - agent_id=agent.id, - messages=[MessageCreateParam(role="user", content=test_message)], - ) - - # List messages and find the user message - messages = client.agents.messages.list(agent_id=agent.id).items - user_messages = [m for m in messages if m.message_type == "user_message"] - assert len(user_messages) > 0, "Expected at least one user message" - - # The user message content should be the raw text (not JSON wrapped) - # When timezone is None, the message is stored as-is and retrieved as-is - latest_user_message = user_messages[0] - assert latest_user_message.content == test_message, f"Expected raw message '{test_message}', got '{latest_user_message.content}'" - finally: - client.agents.delete(agent_id=agent.id) - - -def test_agent_timezone_set_message_packing(client: Letta): - """Test that agent created with timezone has messages JSON wrapped with timestamp.""" - agent = client.agents.create( - memory_blocks=[{"label": "human", "value": ""}, {"label": "persona", "value": ""}], - model="anthropic/claude-haiku-4-5-20251001", - embedding="openai/text-embedding-3-small", - timezone="America/Los_Angeles", - ) - - try: - # Verify timezone is set - retrieved_agent = client.agents.retrieve(agent_id=agent.id) - assert retrieved_agent.timezone == "America/Los_Angeles", f"Expected timezone 'America/Los_Angeles', got {retrieved_agent.timezone}" - - # Send a message - test_message = "Hello, this is a test message with timezone" - client.agents.messages.create( - agent_id=agent.id, - messages=[MessageCreateParam(role="user", content=test_message)], - ) - - # List messages and find the user message - messages = client.agents.messages.list(agent_id=agent.id).items - user_messages = [m for m in messages if m.message_type == "user_message"] - assert len(user_messages) > 0, "Expected at least one user message" - - # The user message content should be unpacked to just the message text - # (The API unpacks the JSON wrapper before returning) - latest_user_message = user_messages[0] - assert latest_user_message.content == test_message, ( - f"Expected unpacked message '{test_message}', got '{latest_user_message.content}'" - ) - - # Test that updating timezone works - client.agents.update(agent_id=agent.id, timezone="America/New_York") - updated_agent = client.agents.retrieve(agent_id=agent.id) - assert updated_agent.timezone == "America/New_York", f"Expected updated timezone 'America/New_York', got {updated_agent.timezone}" - finally: - client.agents.delete(agent_id=agent.id) - - def test_attach_sleeptime_block(client: Letta): agent = client.agents.create( memory_blocks=[{"label": "human", "value": ""}, {"label": "persona", "value": ""}],