Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions crates/aionui-team/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,11 @@ impl TeamSessionService {
|_| {},
);

let carried_run_id = self
.sessions
.get(team_id)
.and_then(|entry| entry.session.team_run_manager().current_active_run_id());

let session = match TeamSession::start_with_prompt_dump(
team,
self.repo.clone(),
Expand Down Expand Up @@ -965,6 +970,14 @@ impl TeamSessionService {
slow_monitor_handle,
};
self.sessions.insert(team_id.to_owned(), entry);
// If the previous session had an active team run, carry it forward so
// team tools (e.g. team_send_message) don't fail with "no active team
// run for run-scoped wake" after a session restart.
if let Some(ref run_id) = carried_run_id {
if let Err(e) = session.team_run_manager().resume_run(run_id.clone()) {
tracing::warn!(team_id, error = %e, "failed to resume team run after session restart");
}
}
drop(membership_guard);
drop(ensure_guard);

Expand Down
28 changes: 28 additions & 0 deletions crates/aionui-team/src/team_run/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,34 @@ impl TeamRunManager {
.map(|run| run.team_run_id.clone())
}

/// Restore a run carried over from a session that was just replaced
/// (e.g. after `ensure_session_inner` recreates the `TeamSession` and its
/// `TeamRunManager`). Without this, `team_send_message` fails with
/// "no active team run for run-scoped wake" because the fresh manager
/// has no run state even though the previous session had one active.
pub(crate) fn resume_run(&self, run_id: String) -> Result<(), TeamError> {
let mut state = self.lock_state();
if state.is_some() {
return Err(TeamError::InvalidRequest(
"cannot resume: a run is already active".into(),
));
}
*state = Some(TeamRunRecord {
team_run_id: run_id,
source: TeamRunSource::SystemLifecycle,
has_user_intervention: false,
target_slot_id: String::new(),
target_role: TeamRunTargetRole::Lead,
status: TeamRunStatus::Accepted,
started_at_ms: None,
completed_at_ms: None,
cancel_reason: None,
summary: None,
accepted_emitted: false,
});
Ok(())
}

pub(crate) fn apply_work_summary(&self, summary: RunWorkSummary) {
let event = {
let mut state = self.lock_state();
Expand Down