sketch: dump message history to /tmp on conversation compaction and include filename in summary
Add dumpMessageHistoryToTmp method that dumps complete agent message history to timestamped JSON file during conversation compaction, returning filename for inclusion in compaction summary message.
When conversation compaction occurs, the agent now:
- Dumps entire a.history array to /tmp/sketch-messages-{sessionID}-{timestamp}.json as formatted JSON
- Returns filename from dumpMessageHistoryToTmp for reference in summary message
- Includes dump file location in compaction summary: "The complete message history has been dumped to {filename} for your reference if needed"
- Continues compaction process even if dump fails to avoid blocking conversation flow
Implementation:
- Added dumpMessageHistoryToTmp method returning (filename, error)
- Modified CompactConversation to call dump before generating summary
- Enhanced summary message to conditionally include dump file reference
- Uses 2-space JSON indentation for readability and 0644 file permissions
- Creates timestamped filenames to avoid conflicts across multiple compactions
The implementation provides access to complete conversation history during epoch restarts while maintaining conversation compaction benefits.
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s3784d6168585f9c4k
diff --git a/loop/agent.go b/loop/agent.go
index c4fc52d..78fdba0 100644
--- a/loop/agent.go
+++ b/loop/agent.go
@@ -628,9 +628,38 @@
return textContent, nil
}
+// dumpMessageHistoryToTmp dumps the agent's entire message history to /tmp as JSON
+// and returns the filename
+func (a *Agent) dumpMessageHistoryToTmp(ctx context.Context) (string, error) {
+ // Create a filename based on session ID and timestamp
+ timestamp := time.Now().Format("20060102-150405")
+ filename := fmt.Sprintf("/tmp/sketch-messages-%s-%s.json", a.config.SessionID, timestamp)
+
+ // Marshal the entire message history to JSON
+ jsonData, err := json.MarshalIndent(a.history, "", " ")
+ if err != nil {
+ return "", fmt.Errorf("failed to marshal message history: %w", err)
+ }
+
+ // Write to file
+ if err := os.WriteFile(filename, jsonData, 0644); err != nil {
+ return "", fmt.Errorf("failed to write message history to %s: %w", filename, err)
+ }
+
+ slog.InfoContext(ctx, "Dumped message history to file", "filename", filename, "message_count", len(a.history))
+ return filename, nil
+}
+
// CompactConversation compacts the current conversation by generating a summary
// and restarting the conversation with that summary as the initial context
func (a *Agent) CompactConversation(ctx context.Context) error {
+ // Dump the entire message history to /tmp as JSON before compacting
+ dumpFile, err := a.dumpMessageHistoryToTmp(ctx)
+ if err != nil {
+ slog.WarnContext(ctx, "Failed to dump message history to /tmp", "error", err)
+ // Continue with compaction even if dump fails
+ }
+
summary, err := a.generateConversationSummary(ctx)
if err != nil {
return fmt.Errorf("failed to generate conversation summary: %w", err)
@@ -662,11 +691,19 @@
Content: compactionMsg,
})
+ // Create the message content with dump file information if available
+ var messageContent string
+ if dumpFile != "" {
+ messageContent = fmt.Sprintf("Here's a summary of our previous work:\n\n%s\n\nThe complete message history has been dumped to %s for your reference if needed.\n\nPlease continue with the work based on this summary.", summary, dumpFile)
+ } else {
+ messageContent = fmt.Sprintf("Here's a summary of our previous work:\n\n%s\n\nPlease continue with the work based on this summary.", summary)
+ }
+
a.pushToOutbox(ctx, AgentMessage{
Type: UserMessageType,
- Content: fmt.Sprintf("Here's a summary of our previous work:\n\n%s\n\nPlease continue with the work based on this summary.", summary),
+ Content: messageContent,
})
- a.inbox <- fmt.Sprintf("Here's a summary of our previous work:\n\n%s\n\nPlease continue with the work based on this summary.", summary)
+ a.inbox <- messageContent
return nil
}