@@ -121,6 +121,9 @@ type Agent struct {
121121 // SessionBackend is the configured backend for session persistence (e.g., memory, filesystem).
122122 SessionBackend string
123123
124+ // sessionManager is a cached SessionManager instance, initialized once in Init.
125+ sessionManager * sessions.SessionManager
126+
124127 // lastErr is the most recent error run into, for use across the stack
125128 lastErr error
126129
@@ -134,6 +137,18 @@ type Agent struct {
134137// Assert InMemoryChatStore implements ChatMessageStore
135138var _ api.ChatMessageStore = & sessions.InMemoryChatStore {}
136139
140+ // getSessionManager returns the cached session manager, lazily initializing it if needed.
141+ func (c * Agent ) getSessionManager () (* sessions.SessionManager , error ) {
142+ if c .sessionManager == nil {
143+ sm , err := sessions .NewSessionManager (c .SessionBackend )
144+ if err != nil {
145+ return nil , fmt .Errorf ("failed to create session manager: %w" , err )
146+ }
147+ c .sessionManager = sm
148+ }
149+ return c .sessionManager , nil
150+ }
151+
137152func (s * Agent ) GetSession () * api.Session {
138153 s .sessionMu .Lock ()
139154 defer s .sessionMu .Unlock ()
@@ -156,7 +171,6 @@ func (c *Agent) addMessage(source api.MessageSource, messageType api.MessageType
156171 Type : messageType ,
157172 Payload : payload ,
158173 Timestamp : time .Now (),
159- Metadata : make (map [string ]string ),
160174 }
161175
162176 // session should always have a ChatMessageStore at this point
@@ -225,6 +239,13 @@ func (s *Agent) Init(ctx context.Context) error {
225239 return fmt .Errorf ("agent requires a session to be provided" )
226240 }
227241
242+ // Initialize session manager for reuse across agent methods
243+ sessionMgr , err := sessions .NewSessionManager (s .SessionBackend )
244+ if err != nil {
245+ return fmt .Errorf ("failed to create session manager: %w" , err )
246+ }
247+ s .sessionManager = sessionMgr
248+
228249 // Create a session working directory in the user's home directory
229250 // to avoid read-only filesystem issues in containers
230251 homeDir , err := os .UserHomeDir ()
@@ -595,7 +616,7 @@ func (c *Agent) Run(ctx context.Context, initialQuery string) error {
595616 msg := c .addMessage (api .MessageSourceModel , api .MessageTypeText , streamedText )
596617 // If no function calls to be made, this is the final message of the turn
597618 if len (functionCalls ) == 0 {
598- msg .Metadata [ "is_final" ] = "true"
619+ msg .SetMetadata ( "is_final" , "true" )
599620 }
600621 }
601622 // If no function calls to be made, we're done
@@ -612,7 +633,7 @@ func (c *Agent) Run(ctx context.Context, initialQuery string) error {
612633 // IMPORTANT: This also prevents UIs from getting blocked on reading from the output channel.
613634 log .V (2 ).Info ("Empty response with no tool calls from LLM." )
614635 msg := c .addMessage (api .MessageSourceAgent , api .MessageTypeText , "Empty response from LLM" )
615- msg .Metadata [ "is_final" ] = "true"
636+ msg .SetMetadata ( "is_final" , "true" )
616637 }
617638 continue
618639 }
@@ -788,12 +809,11 @@ func (c *Agent) handleMetaQuery(ctx context.Context, query string) (answer strin
788809 return "Saved session as " + savedSessionID , true , nil
789810
790811 case "sessions" :
791- manager , err := sessions . NewSessionManager ( c . SessionBackend )
812+ mgr , err := c . getSessionManager ( )
792813 if err != nil {
793- return "" , false , fmt . Errorf ( "failed to create session manager: %w" , err )
814+ return "" , false , err
794815 }
795-
796- sessionList , err := manager .ListSessions ()
816+ sessionList , err := mgr .ListSessions ()
797817 if err != nil {
798818 return "" , false , fmt .Errorf ("failed to list sessions: %w" , err )
799819 }
@@ -840,11 +860,6 @@ func (c *Agent) NewSession() (string, error) {
840860 return "" , fmt .Errorf ("failed to save current session: %w" , err )
841861 }
842862
843- manager , err := sessions .NewSessionManager (c .SessionBackend )
844- if err != nil {
845- return "" , fmt .Errorf ("failed to create session manager: %w" , err )
846- }
847-
848863 metadata := sessions.Metadata {
849864 ModelID : c .Model ,
850865 ProviderID : c .Provider ,
@@ -853,7 +868,11 @@ func (c *Agent) NewSession() (string, error) {
853868 metadata .SlackUserID = c .Session .SlackUserID
854869 }
855870
856- newSession , err := manager .NewSession (metadata )
871+ mgr , err := c .getSessionManager ()
872+ if err != nil {
873+ return "" , err
874+ }
875+ newSession , err := mgr .NewSession (metadata )
857876 if err != nil {
858877 return "" , fmt .Errorf ("failed to create new session: %w" , err )
859878 }
@@ -910,13 +929,13 @@ func (c *Agent) SaveSession() (string, error) {
910929 c .sessionMu .Lock ()
911930 defer c .sessionMu .Unlock ()
912931
913- manager , err := sessions . NewSessionManager ( c . SessionBackend )
932+ mgr , err := c . getSessionManager ( )
914933 if err != nil {
915- return "" , fmt . Errorf ( "failed to create session manager: %w" , err )
934+ return "" , err
916935 }
917936
918937 if c .Session != nil {
919- foundSession , _ := manager .FindSessionByID (c .Session .ID )
938+ foundSession , _ := mgr .FindSessionByID (c .Session .ID )
920939 if foundSession != nil {
921940 return foundSession .ID , nil
922941 }
@@ -930,7 +949,7 @@ func (c *Agent) SaveSession() (string, error) {
930949 SlackUserID : c .Session .SlackUserID ,
931950 }
932951
933- newSession , err := manager .NewSession (metadata )
952+ newSession , err := mgr .NewSession (metadata )
934953 if err != nil {
935954 return "" , fmt .Errorf ("failed to create new session: %w" , err )
936955 }
@@ -953,14 +972,14 @@ func (c *Agent) SaveSession() (string, error) {
953972
954973// LoadSession loads a session by ID (or latest), updates the agent's state, and re-initializes the chat.
955974func (c * Agent ) LoadSession (sessionID string ) error {
956- manager , err := sessions . NewSessionManager ( c . SessionBackend )
975+ mgr , err := c . getSessionManager ( )
957976 if err != nil {
958- return fmt . Errorf ( "failed to create session manager: %w" , err )
977+ return err
959978 }
960979
961980 var session * api.Session
962981 if sessionID == "" || sessionID == "latest" {
963- s , err := manager .GetLatestSession ()
982+ s , err := mgr .GetLatestSession ()
964983 if err != nil {
965984 return fmt .Errorf ("failed to get latest session: %w" , err )
966985 }
@@ -969,7 +988,7 @@ func (c *Agent) LoadSession(sessionID string) error {
969988 }
970989 session = s
971990 } else {
972- s , err := manager .FindSessionByID (sessionID )
991+ s , err := mgr .FindSessionByID (sessionID )
973992 if err != nil {
974993 return fmt .Errorf ("failed to get session %q: %w" , sessionID , err )
975994 }
@@ -993,7 +1012,7 @@ func (c *Agent) LoadSession(sessionID string) error {
9931012 c .Session .AgentState = api .AgentStateIdle
9941013 }
9951014
996- if err := manager .UpdateLastAccessed (session ); err != nil {
1015+ if err := mgr .UpdateLastAccessed (session ); err != nil {
9971016 return fmt .Errorf ("failed to update session metadata: %w" , err )
9981017 }
9991018
@@ -1262,7 +1281,7 @@ func toMap(v any) (map[string]any, error) {
12621281
12631282func candidateToShimCandidate (iterator gollm.ChatResponseIterator ) (gollm.ChatResponseIterator , error ) {
12641283 return func (yield func (gollm.ChatResponse , error ) bool ) {
1265- buffer := ""
1284+ var buf strings. Builder
12661285 for response , err := range iterator {
12671286 if err != nil {
12681287 yield (nil , err )
@@ -1278,7 +1297,7 @@ func candidateToShimCandidate(iterator gollm.ChatResponseIterator) (gollm.ChatRe
12781297
12791298 for _ , part := range candidate .Parts () {
12801299 if text , ok := part .AsText (); ok {
1281- buffer += text
1300+ buf . WriteString ( text )
12821301 klog .Infof ("text is %q" , text )
12831302 } else {
12841303 yield (nil , fmt .Errorf ("no text part found in candidate" ))
@@ -1287,6 +1306,7 @@ func candidateToShimCandidate(iterator gollm.ChatResponseIterator) (gollm.ChatRe
12871306 }
12881307 }
12891308
1309+ buffer := buf .String ()
12901310 if buffer == "" {
12911311 yield (nil , nil )
12921312 return
0 commit comments