@@ -37,6 +37,18 @@ type AgentState struct {
3737 InitialPromptSent bool `json:"initial_prompt_sent"`
3838}
3939
40+ // LoadStateStatus represents the state of loading persisted conversation state.
41+ type LoadStateStatus int
42+
43+ const (
44+ // LoadStatePending indicates state loading has not been attempted yet.
45+ LoadStatePending LoadStateStatus = iota
46+ // LoadStateSucceeded indicates state was successfully loaded.
47+ LoadStateSucceeded
48+ // LoadStateFailed indicates state loading was attempted but failed.
49+ LoadStateFailed
50+ )
51+
4052var _ MessagePart = & MessagePartText {}
4153
4254func (p MessagePartText ) Do (writer AgentIO ) error {
@@ -125,8 +137,8 @@ type PTYConversation struct {
125137 firstStableSnapshot string
126138 // userSentMessageAfterLoadState tracks if the user has sent their first message after we load the state
127139 userSentMessageAfterLoadState bool
128- // loadStateAttempted indicates whether we have attempted to load conversation state from file (regardless of success) .
129- loadStateAttempted bool
140+ // loadStateStatus tracks the status of loading conversation state from file.
141+ loadStateStatus LoadStateStatus
130142 // initialPromptReady is set to true when ReadyForInitialPrompt returns true.
131143 // Checked inline in the snapshot loop on each tick.
132144 initialPromptReady bool
@@ -169,7 +181,7 @@ func NewPTY(ctx context.Context, cfg PTYConversationConfig, emitter Emitter) *PT
169181 dirty : false ,
170182 firstStableSnapshot : "" ,
171183 userSentMessageAfterLoadState : false ,
172- loadStateAttempted : false ,
184+ loadStateStatus : LoadStatePending ,
173185 }
174186 if c .cfg .ReadyForInitialPrompt == nil {
175187 c .cfg .ReadyForInitialPrompt = func (string ) bool { return true }
@@ -193,13 +205,14 @@ func (c *PTYConversation) Start(ctx context.Context) {
193205 c .initialPromptReady = true
194206 }
195207
196- var loadStateErr error
197- if c .initialPromptReady && ! c .loadStateAttempted && c .cfg .StatePersistenceConfig .LoadState {
208+ if c .initialPromptReady && c .loadStateStatus == LoadStatePending && c .cfg .StatePersistenceConfig .LoadState {
198209 if err := c .loadStateLocked (); err != nil {
199210 c .cfg .Logger .Error ("Failed to load state" , "error" , err )
200- loadStateErr = err
211+ c .emitter .EmitError (fmt .Sprintf ("Failed to restore previous session: %v" , err ), "warning" )
212+ c .loadStateStatus = LoadStateFailed
213+ } else {
214+ c .loadStateStatus = LoadStateSucceeded
201215 }
202- c .loadStateAttempted = true
203216 }
204217
205218 // Enqueue initial prompt once after agent is ready (and after state is potentially loaded)
@@ -222,9 +235,6 @@ func (c *PTYConversation) Start(ctx context.Context) {
222235 c .emitter .EmitStatus (status )
223236 c .emitter .EmitMessages (messages )
224237 c .emitter .EmitScreen (screen )
225- if loadStateErr != nil {
226- c .emitter .EmitError (fmt .Sprintf ("Failed to restore previous session: %v" , loadStateErr ), "warning" )
227- }
228238 return nil
229239 }, "snapshot" )
230240
@@ -288,7 +298,7 @@ func (c *PTYConversation) updateLastAgentMessageLocked(screen string, timestamp
288298 if c .cfg .FormatMessage != nil {
289299 agentMessage = c .cfg .FormatMessage (agentMessage , lastUserMessage .Message )
290300 }
291- if c .loadStateAttempted {
301+ if c .loadStateStatus == LoadStateSucceeded {
292302 agentMessage = c .adjustScreenAfterStateLoad (agentMessage )
293303 }
294304 if c .cfg .FormatToolCall != nil {
@@ -607,7 +617,7 @@ func (c *PTYConversation) loadStateLocked() error {
607617 stateFile := c .cfg .StatePersistenceConfig .StateFile
608618 loadState := c .cfg .StatePersistenceConfig .LoadState
609619
610- if ! loadState || c .loadStateAttempted {
620+ if ! loadState || c .loadStateStatus != LoadStatePending {
611621 return nil
612622 }
613623
@@ -662,7 +672,6 @@ func (c *PTYConversation) loadStateLocked() error {
662672 c .firstStableSnapshot = c .cfg .FormatMessage (strings .TrimSpace (snapshots [len (snapshots )- 1 ].screen ), "" )
663673 }
664674
665- c .loadStateAttempted = true
666675 c .dirty = false
667676
668677 c .cfg .Logger .Info ("Successfully loaded state" , "path" , stateFile , "messages" , len (c .messages ))
0 commit comments