22
33import json
44import logging
5- from dataclasses import asdict
65from typing import Any , Dict , List , Optional , cast
76
87import boto3
@@ -85,22 +84,18 @@ def _get_agent_path(self, session_id: str, agent_id: str) -> str:
8584 session_path = self ._get_session_path (session_id )
8685 return f"{ session_path } agents/{ AGENT_PREFIX } { agent_id } /"
8786
88- def _get_message_path (self , session_id : str , agent_id : str , message_id : str , timestamp : str ) -> str :
87+ def _get_message_path (self , session_id : str , agent_id : str , message_id : int ) -> str :
8988 """Get message S3 key.
9089
9190 Args:
9291 session_id: ID of the session
9392 agent_id: ID of the agent
94- message_id: ID of the message
95- timestamp: ISO format timestamp to include in key for sorting
93+ message_id: Index of the message
9694 Returns:
9795 The key for the message
9896 """
9997 agent_path = self ._get_agent_path (session_id , agent_id )
100- # Use timestamp for sortable keys
101- # Replace colons and periods in ISO format with underscores for filesystem compatibility
102- filename_timestamp = timestamp .replace (":" , "_" ).replace ("." , "_" )
103- return f"{ agent_path } messages/{ MESSAGE_PREFIX } { filename_timestamp } _{ message_id } .json"
98+ return f"{ agent_path } messages/{ MESSAGE_PREFIX } { message_id } .json"
10499
105100 def _read_s3_object (self , key : str ) -> Optional [Dict [str , Any ]]:
106101 """Read JSON object from S3."""
@@ -139,7 +134,7 @@ def create_session(self, session: Session) -> Session:
139134 raise SessionException (f"S3 error checking session existence: { e } " ) from e
140135
141136 # Write session object
142- session_dict = asdict ( session )
137+ session_dict = session . to_dict ( )
143138 self ._write_s3_object (session_key , session_dict )
144139 return session
145140
@@ -177,7 +172,7 @@ def delete_session(self, session_id: str) -> None:
177172 def create_agent (self , session_id : str , session_agent : SessionAgent ) -> None :
178173 """Create a new agent in S3."""
179174 agent_id = session_agent .agent_id
180- agent_dict = asdict ( session_agent )
175+ agent_dict = session_agent . to_dict ( )
181176 agent_key = f"{ self ._get_agent_path (session_id , agent_id )} agent.json"
182177 self ._write_s3_object (agent_key , agent_dict )
183178
@@ -199,35 +194,22 @@ def update_agent(self, session_id: str, session_agent: SessionAgent) -> None:
199194 # Preserve creation timestamp
200195 session_agent .created_at = previous_agent .created_at
201196 agent_key = f"{ self ._get_agent_path (session_id , agent_id )} agent.json"
202- self ._write_s3_object (agent_key , asdict ( session_agent ))
197+ self ._write_s3_object (agent_key , session_agent . to_dict ( ))
203198
204199 def create_message (self , session_id : str , agent_id : str , session_message : SessionMessage ) -> None :
205200 """Create a new message in S3."""
206201 message_id = session_message .message_id
207- message_dict = asdict ( session_message )
208- message_key = self ._get_message_path (session_id , agent_id , message_id , session_message . created_at )
202+ message_dict = session_message . to_dict ( )
203+ message_key = self ._get_message_path (session_id , agent_id , message_id )
209204 self ._write_s3_object (message_key , message_dict )
210205
211- def read_message (self , session_id : str , agent_id : str , message_id : str ) -> Optional [SessionMessage ]:
206+ def read_message (self , session_id : str , agent_id : str , message_id : int ) -> Optional [SessionMessage ]:
212207 """Read message data from S3."""
213- # Get the messages prefix
214- messages_prefix = f"{ self ._get_agent_path (session_id , agent_id )} messages/"
215- try :
216- paginator = self .client .get_paginator ("list_objects_v2" )
217- pages = paginator .paginate (Bucket = self .bucket , Prefix = messages_prefix )
218-
219- for page in pages :
220- if "Contents" in page :
221- for obj in page ["Contents" ]:
222- if obj ["Key" ].endswith (f"{ message_id } .json" ):
223- message_data = self ._read_s3_object (obj ["Key" ])
224- if message_data :
225- return SessionMessage .from_dict (message_data )
226-
208+ message_key = self ._get_message_path (session_id , agent_id , message_id )
209+ message_data = self ._read_s3_object (message_key )
210+ if message_data is None :
227211 return None
228-
229- except ClientError as e :
230- raise SessionException (f"S3 error reading message: { e } " ) from e
212+ return SessionMessage .from_dict (message_data )
231213
232214 def update_message (self , session_id : str , agent_id : str , session_message : SessionMessage ) -> None :
233215 """Update message data in S3."""
@@ -238,8 +220,8 @@ def update_message(self, session_id: str, agent_id: str, session_message: Sessio
238220
239221 # Preserve creation timestamp
240222 session_message .created_at = previous_message .created_at
241- message_key = self ._get_message_path (session_id , agent_id , message_id , session_message . created_at )
242- self ._write_s3_object (message_key , asdict ( session_message ))
223+ message_key = self ._get_message_path (session_id , agent_id , message_id )
224+ self ._write_s3_object (message_key , session_message . to_dict ( ))
243225
244226 def list_messages (
245227 self , session_id : str , agent_id : str , limit : Optional [int ] = None , offset : int = 0
@@ -250,16 +232,21 @@ def list_messages(
250232 paginator = self .client .get_paginator ("list_objects_v2" )
251233 pages = paginator .paginate (Bucket = self .bucket , Prefix = messages_prefix )
252234
253- # Collect all message keys first
254- message_keys = []
235+ # Collect all message keys and extract their indices
236+ message_index_keys : list [ tuple [ int , str ]] = []
255237 for page in pages :
256238 if "Contents" in page :
257239 for obj in page ["Contents" ]:
258- if obj ["Key" ].endswith (".json" ) and MESSAGE_PREFIX in obj ["Key" ]:
259- message_keys .append (obj ["Key" ])
260-
261- # Sort keys - timestamp prefixed keys will sort chronologically
262- message_keys .sort ()
240+ key = obj ["Key" ]
241+ if key .endswith (".json" ) and MESSAGE_PREFIX in key :
242+ # Extract the filename part from the full S3 key
243+ filename = key .split ("/" )[- 1 ]
244+ # Extract index from message_<index>.json format
245+ index = int (filename [len (MESSAGE_PREFIX ) : - 5 ]) # Remove prefix and .json suffix
246+ message_index_keys .append ((index , key ))
247+
248+ # Sort by index and extract just the keys
249+ message_keys = [k for _ , k in sorted (message_index_keys )]
263250
264251 # Apply pagination to keys before loading content
265252 if limit is not None :
0 commit comments