@@ -163,8 +163,14 @@ def setup_file_path(self):
163163 extension = (
164164 ".json" if self .export_method == "json" else ".yaml"
165165 )
166- self .save_filepath = (
167- f"conversation_{ self .name } { extension } "
166+ # Under conversations_dir, not the process's working directory:
167+ # a bare relative name dropped conversation_<name>.json wherever
168+ # the program happened to run from, and two conversations sharing
169+ # a name in different directories silently loaded each other's
170+ # history.
171+ self .save_filepath = os .path .join (
172+ self .conversations_dir or get_conversation_dir (),
173+ f"conversation_{ self .name } { extension } " ,
168174 )
169175 logger .debug (
170176 f"Setting default save filepath to: { self .save_filepath } "
@@ -934,6 +940,41 @@ def export(self, force: bool = True):
934940 )
935941 raise # Re-raise to ensure the error is visible
936942
943+ def _restore (self , data : Union [dict , list ]):
944+ """Apply a loaded save file to this conversation.
945+
946+ Accepts both shapes a save file can have. ``save_as_json`` and
947+ ``save_as_yaml`` write ``to_dict()``, which is the bare list of
948+ messages, while this loader only understood a
949+ ``{"metadata": ..., "conversation_history": ...}`` wrapper — so
950+ reloading a file this class had just written raised
951+ ``AttributeError: 'list' object has no attribute 'get'``.
952+
953+ Args:
954+ data (Union[dict, list]): Parsed contents of a save file.
955+ """
956+ if isinstance (data , list ):
957+ self .conversation_history = data
958+ self ._str_cache = None
959+ return
960+
961+ if not isinstance (data , dict ):
962+ logger .warning (
963+ f"Ignoring save file with unexpected top-level "
964+ f"{ type (data ).__name__ } ; expected a list or a dict."
965+ )
966+ return
967+
968+ # Conversation-level settings, when the file carries the wrapper.
969+ for key , value in (data .get ("metadata" ) or {}).items ():
970+ if hasattr (self , key ):
971+ setattr (self , key , value )
972+
973+ self .conversation_history = data .get (
974+ "conversation_history" , []
975+ )
976+ self ._str_cache = None
977+
937978 def load_from_json (self , filename : str ):
938979 """Load the conversation history and metadata from a JSON file.
939980
@@ -945,18 +986,7 @@ def load_from_json(self, filename: str):
945986 with open (filename , "r" , encoding = "utf-8" ) as f :
946987 data = json .load (f )
947988
948- # Load metadata
949- metadata = data .get ("metadata" , {})
950- # Update all metadata attributes
951- for key , value in metadata .items ():
952- if hasattr (self , key ):
953- setattr (self , key , value )
954-
955- # Load conversation history
956- self .conversation_history = data .get (
957- "conversation_history" , []
958- )
959- self ._str_cache = None
989+ self ._restore (data )
960990
961991 logger .info (
962992 f"Successfully loaded conversation from { filename } "
@@ -978,18 +1008,7 @@ def load_from_yaml(self, filename: str):
9781008 with open (filename , "r" , encoding = "utf-8" ) as f :
9791009 data = yaml .safe_load (f )
9801010
981- # Load metadata
982- metadata = data .get ("metadata" , {})
983- # Update all metadata attributes
984- for key , value in metadata .items ():
985- if hasattr (self , key ):
986- setattr (self , key , value )
987-
988- # Load conversation history
989- self .conversation_history = data .get (
990- "conversation_history" , []
991- )
992- self ._str_cache = None
1011+ self ._restore (data )
9931012
9941013 logger .info (
9951014 f"Successfully loaded conversation from { filename } "
0 commit comments