Resume a previously-checkpointed run on this session (P3 cut 2). Loads the latest [`LoopCheckpoint`](crate::loop_checkpoint::LoopCheckpoint) for `checkpoint_run_id` from the session's `SessionStore` and replays the agent loop from that boundary state. A **new** run id is generated for the resumed work — the relationship between the old and new run is metadata the host tracks externally. Returns
(
session: &AgentSession,
checkpoint_run_id: &str,
)
| 99 | /// Returns an error when the session has no store configured, or when |
| 100 | /// no checkpoint exists for `checkpoint_run_id`. |
| 101 | pub(super) async fn resume_run( |
| 102 | session: &AgentSession, |
| 103 | checkpoint_run_id: &str, |
| 104 | ) -> Result<crate::agent::AgentResult> { |
| 105 | bail_if_closed(session)?; |
| 106 | |
| 107 | let store = session.session_store.as_ref().ok_or_else(|| { |
| 108 | CodeError::Session("resume_run requires a session_store on this session".to_string()) |
| 109 | })?; |
| 110 | |
| 111 | let checkpoint = store |
| 112 | .load_loop_checkpoint(checkpoint_run_id) |
| 113 | .await |
| 114 | .map_err(|e| { |
| 115 | CodeError::Session(format!( |
| 116 | "load_loop_checkpoint('{checkpoint_run_id}') failed: {e}" |
| 117 | )) |
| 118 | })? |
| 119 | .ok_or_else(|| { |
| 120 | CodeError::Session(format!( |
| 121 | "no loop checkpoint found for run '{checkpoint_run_id}'" |
| 122 | )) |
| 123 | })?; |
| 124 | |
| 125 | let persistence = |
| 126 | Some(super::session_persistence::SessionPersistenceContext::from_session(session)); |
| 127 | let blocking_run = BlockingRunContext::start( |
| 128 | session, |
| 129 | &format!("<resume run={checkpoint_run_id} turn={}>", checkpoint.turn), |
| 130 | persistence, |
| 131 | ) |
| 132 | .await; |
| 133 | // Seed the resumed run's loop state with the cumulative metrics from |
| 134 | // the checkpoint so token usage and tool-call counts continue from |
| 135 | // where the crashed/migrated run left off rather than re-starting at |
| 136 | // zero (which would under-report the resumed AgentResult). |
| 137 | let seed = crate::agent::ExecutionSeed { |
| 138 | total_usage: checkpoint.total_usage.clone(), |
| 139 | tool_calls_count: checkpoint.tool_calls_count, |
| 140 | verification_reports: checkpoint.verification_reports.clone(), |
| 141 | }; |
| 142 | blocking_run |
| 143 | .execute_from_messages_seeded(checkpoint.messages, &session.session_id, Some(seed)) |
| 144 | .await |
| 145 | } |
| 146 | |
| 147 | fn warn_deferred_init(session: &AgentSession) { |
| 148 | if let Some(warning) = &session.init_warning { |
no test coverage detected