-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Add conversation history and resume functionality #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
c766d88
feat: implement conversation history and resume functionality
nachoal 59fe952
fix(history): resolve session picker and display issues
nachoal 290a9fc
fix: address PR review comments from auto-reviewer
nachoal cb3b0a9
fix: add proper error logging for session save failures
nachoal 5f9f79d
fix: add proper locking to prevent race conditions in metadata access
nachoal e162798
fix: capture complete conversation history including tool interactions
nachoal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| package agent | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "os" | ||
|
|
||
| "github.com/nachoal/simple-agent-go/history" | ||
| ) | ||
|
|
||
| // HistoryAgent wraps an agent with conversation history support | ||
| type HistoryAgent struct { | ||
| Agent | ||
| historyManager *history.Manager | ||
| currentSession *history.Session | ||
| } | ||
|
|
||
| // NewHistoryAgent creates a new agent with history support | ||
| func NewHistoryAgent(agent Agent, historyManager *history.Manager, session *history.Session) *HistoryAgent { | ||
| return &HistoryAgent{ | ||
| Agent: agent, | ||
| historyManager: historyManager, | ||
| currentSession: session, | ||
| } | ||
| } | ||
|
|
||
| // Query sends a query and saves the conversation to history | ||
| func (ha *HistoryAgent) Query(ctx context.Context, query string) (*Response, error) { | ||
| // Remember the initial message count to rollback on failure | ||
| initialMessageCount := 0 | ||
| if ha.currentSession != nil { | ||
| initialMessageCount = len(ha.currentSession.Messages) | ||
| } | ||
|
|
||
| // Execute query first | ||
| response, err := ha.Agent.Query(ctx, query) | ||
|
|
||
| // If successful, update history with the complete conversation | ||
| if err == nil && ha.currentSession != nil { | ||
| // Get the complete memory from the agent (includes all tool interactions) | ||
| agentMemory := ha.Agent.GetMemory() | ||
|
|
||
| // Convert and store all new messages since our last save | ||
| // We need to sync our session with the agent's memory | ||
| ha.currentSession.Messages = ha.historyManager.ConvertFromLLMMessages(agentMemory) | ||
|
|
||
| // Save session with complete history | ||
| if saveErr := ha.historyManager.SaveSession(ha.currentSession); saveErr != nil { | ||
| // Log error but don't fail the query | ||
| fmt.Fprintf(os.Stderr, "\n[WARNING] Failed to save conversation history: %v\n", saveErr) | ||
| fmt.Fprintf(os.Stderr, "Your conversation may not be saved. Please check disk space and permissions.\n\n") | ||
| } | ||
| } else if err != nil && ha.currentSession != nil { | ||
| // Query failed - rollback to initial state | ||
| ha.currentSession.Messages = ha.currentSession.Messages[:initialMessageCount] | ||
| } | ||
|
|
||
| return response, err | ||
| } | ||
|
|
||
| // QueryStream sends a query and streams the response while saving to history | ||
| func (ha *HistoryAgent) QueryStream(ctx context.Context, query string) (<-chan StreamEvent, error) { | ||
| // Remember the initial message count to rollback on failure | ||
| initialMessageCount := 0 | ||
| if ha.currentSession != nil { | ||
| initialMessageCount = len(ha.currentSession.Messages) | ||
| } | ||
|
cursor[bot] marked this conversation as resolved.
|
||
|
|
||
| // Get the stream | ||
| events, err := ha.Agent.QueryStream(ctx, query) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // Create a new channel to intercept events | ||
| intercepted := make(chan StreamEvent, 100) | ||
|
|
||
| go func() { | ||
| defer close(intercepted) | ||
|
|
||
| streamSucceeded := false | ||
|
|
||
| for event := range events { | ||
| // Forward the event | ||
| intercepted <- event | ||
|
|
||
| // Check for completion or error | ||
| switch event.Type { | ||
| case EventTypeComplete: | ||
| streamSucceeded = true | ||
| // Get the complete memory from the agent (includes all tool interactions) | ||
| if ha.currentSession != nil { | ||
| agentMemory := ha.Agent.GetMemory() | ||
| ha.currentSession.Messages = ha.historyManager.ConvertFromLLMMessages(agentMemory) | ||
|
|
||
| // Save session with complete history | ||
| if err := ha.historyManager.SaveSession(ha.currentSession); err != nil { | ||
| // Send error event through the stream | ||
| intercepted <- StreamEvent{ | ||
| Type: EventTypeError, | ||
| Error: fmt.Errorf("failed to save conversation history: %w", err), | ||
| } | ||
| // Also log to stderr | ||
| fmt.Fprintf(os.Stderr, "\n[WARNING] Failed to save conversation history: %v\n", err) | ||
| } | ||
| } | ||
| case EventTypeError: | ||
| // Stream failed - rollback the session | ||
| if ha.currentSession != nil && !streamSucceeded { | ||
| ha.currentSession.Messages = ha.currentSession.Messages[:initialMessageCount] | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // If stream ended without completion or error, rollback | ||
| if !streamSucceeded && ha.currentSession != nil { | ||
| ha.currentSession.Messages = ha.currentSession.Messages[:initialMessageCount] | ||
| } | ||
| }() | ||
|
|
||
| return intercepted, nil | ||
| } | ||
|
|
||
| // GetSession returns the current session | ||
| func (ha *HistoryAgent) GetSession() *history.Session { | ||
| return ha.currentSession | ||
| } | ||
|
|
||
| // SetSession updates the current session | ||
| func (ha *HistoryAgent) SetSession(session *history.Session) { | ||
| ha.currentSession = session | ||
| } | ||
|
|
||
| // RestoreMemoryFromSession restores the agent's memory from a session | ||
| func (ha *HistoryAgent) RestoreMemoryFromSession(session *history.Session) { | ||
| if session == nil || len(session.Messages) == 0 { | ||
| return | ||
| } | ||
|
|
||
| // Convert and restore messages | ||
| llmMessages := ha.historyManager.ConvertToLLMMessages(session.Messages) | ||
|
|
||
| // Set the memory directly | ||
| ha.Agent.SetMemory(llmMessages) | ||
|
|
||
| // Update current session | ||
| ha.currentSession = session | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.