diff options
| author | Castor Gemini <[email protected]> | 2025-08-22 02:14:17 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2025-08-22 02:14:17 -0500 |
| commit | 3b6b85200d9d42698a58c52b87f6b7ab56a4a99a (patch) | |
| tree | 44d9d138c3f67e8e21c6871659ad96613f57e9ce | |
| parent | 80090152a19af0e93fefe738b0bbebc912010e29 (diff) | |
fix(chatpb): Update AddFile to support nested chat entries
- The AddFile function now correctly parses both the old flat log
format and the new format where chats are grouped by topic.
- It flattens the new structure by iterating through the 'Entries'
of a chat group and appending them to the main chat list.
- This allows the application to transparently load both old and
new log files.
| -rw-r--r-- | helpers.go | 104 |
1 files changed, 83 insertions, 21 deletions
@@ -48,6 +48,14 @@ func UnmarshalChatsTEXT(data []byte) (*Chats, error) { } func (all *Chats) AddFile(filename string) error { + // Nil checks for safety. + if all == nil { + return fmt.Errorf("cannot call AddFile on a nil *Chats object") + } + if all.Chats == nil { + all.Chats = make([]*Chat, 0) + } + data, err := os.ReadFile(filename) if err != nil { log.Fatalf("Error reading file %s: %v", filename, err) @@ -60,35 +68,89 @@ func (all *Chats) AddFile(filename string) error { return err } - for _, chat := range logData.GetChats() { - // make a copy - newc := proto.Clone(chat).(*Chat) + // Iterate through the top-level messages from the source file. + for _, chatGroup := range logData.GetChats() { + if len(chatGroup.GetEntries()) > 0 { + // NEW FORMAT: This is a group, process its entries. + for _, entry := range chatGroup.GetEntries() { + // Convert the ChatEntry into a new Chat object for the flat list. + newChat := convertEntryToChat(entry, filename) + if newChat != nil { + newChat.VerifyUuid() + all.AppendByUuid(newChat) + } + } + } else { + // OLD FORMAT: This is a single, flat Chat message. + // We still process it to handle its external content file correctly. + newChat := convertChatToChat(chatGroup, filename) + if newChat != nil { + newChat.VerifyUuid() + all.AppendByUuid(newChat) + } + } + } + return nil +} - // Handle content: prefer content_file, fallback to content. - var content string - if contentFile := chat.GetContentFile(); contentFile != "" { - // Construct the full path relative to the log file's directory. - logDir := filepath.Dir(filename) - contentPath := filepath.Join(logDir, contentFile) +// convertChatToChat handles an old-style Chat message. It creates a clean +// copy and resolves its external content file. +func convertChatToChat(chat *Chat, filename string) *Chat { + if chat == nil { + return nil + } - contentBytes, err := os.ReadFile(contentPath) - if err != nil { - content = fmt.Sprintf("--- ERROR: Could not read content file %s: %v ---", contentPath, err) - } else { - content = string(contentBytes) - } + // Manually create a ChatEntry from the Chat fields to reuse the logic. + entry := &ChatEntry{ + From: chat.GetFrom(), + Ctime: chat.GetCtime(), + Content: chat.GetContent(), + Table: chat.GetTable(), + ToolCalls: chat.GetToolCalls(), + ContentFile: chat.GetContentFile(), + Uuid: chat.GetUuid(), + Snippets: chat.GetSnippets(), + } + return convertEntryToChat(entry, filename) +} + +// convertEntryToChat creates a new Chat object from a ChatEntry's data +// and resolves its external content file. +func convertEntryToChat(entry *ChatEntry, filename string) *Chat { + if entry == nil { + return nil + } + + // Create a new Chat object and copy the fields. + newChat := &Chat{ + From: entry.GetFrom(), + Ctime: entry.GetCtime(), + Table: entry.GetTable(), + ToolCalls: entry.GetToolCalls(), + Snippets: entry.GetSnippets(), + Uuid: entry.GetUuid(), + } + + // Handle content: prefer content_file, fallback to content. + var content string + if contentFile := entry.GetContentFile(); contentFile != "" { + logDir := filepath.Dir(filename) + contentPath := filepath.Join(logDir, contentFile) + contentBytes, err := os.ReadFile(contentPath) + if err != nil { + content = fmt.Sprintf("--- ERROR: Could not read content file %s: %v ---", contentPath, err) } else { - // Fallback for older log formats. - content = chat.GetContent() + content = string(contentBytes) } - newc.Content = content - newc.VerifyUuid() - all.AppendNew(newc) + } else { + content = entry.GetContent() } + newChat.Content = content - return nil + return newChat } + func (chats *Chats) VerifyUuids() bool { var changed bool |
