agent: save session after each tool round for mid-turn crash recovery
Adds SaveSession callback to agentConfig, called after every state.update() in the run loop. On restart, the session JSON contains all completed tool rounds; the model continues naturally from current history. SIGTERM is already handled in olliesrv via InterruptAll + Shutdown, which cancels all session contexts and lets the loop exit cleanly after the current state.update(). Worst-case (SIGKILL) loses one tool round, not the whole turn. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
eabe17a1b1
commit
dc83763c24
|
|
@ -777,6 +777,7 @@ func (s *agent) executeTurn(ctx context.Context, input string, handler EventHand
|
|||
"result": result,
|
||||
}, s.log)
|
||||
}
|
||||
s.cfg.SaveSession = func() { s.saveSession() }
|
||||
s.cfg.AutoCompact = func(ctx context.Context) {
|
||||
if ctx.Err() != nil || s.session == nil {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ type agentConfig struct {
|
|||
GenerationParams backend.GenerationParams
|
||||
PopInject func() string // returns and clears pending inject, or ""
|
||||
AutoCompact func(ctx context.Context) // called after each tool round; may compact in-place
|
||||
SaveSession func() // called after each state.update(); persists mid-turn progress
|
||||
PreTool func(ctx context.Context, name string, args json.RawMessage) HookResult // called before each tool; exit 2 blocks execution
|
||||
PostTool func(ctx context.Context, name string, args json.RawMessage, result string) HookResult // called after each tool; exit 0 appends, exit 2 replaces result
|
||||
}
|
||||
|
|
@ -127,6 +128,9 @@ func run(ctx context.Context, cfg agentConfig, state state) error {
|
|||
})
|
||||
}
|
||||
state.update(msg, results)
|
||||
if cfg.SaveSession != nil {
|
||||
cfg.SaveSession()
|
||||
}
|
||||
return fmt.Errorf("step %d: stream interrupted: %w", step, ctx.Err())
|
||||
}
|
||||
|
||||
|
|
@ -252,6 +256,9 @@ func run(ctx context.Context, cfg agentConfig, state state) error {
|
|||
}
|
||||
|
||||
state.update(msg, results)
|
||||
if cfg.SaveSession != nil {
|
||||
cfg.SaveSession()
|
||||
}
|
||||
|
||||
if interrupted {
|
||||
return ctx.Err()
|
||||
|
|
|
|||
Reference in New Issue