crash_watch: track prev_sub_agents to fix needs_login for newly spawned agents
This commit is contained in:
parent
55fe2856b9
commit
7426654a74
2 changed files with 26 additions and 31 deletions
|
|
@ -210,24 +210,12 @@ fn finish_approval(
|
|||
});
|
||||
}
|
||||
}
|
||||
ApprovalKind::Spawn => {
|
||||
coord.notify_manager(&HelperEvent::Spawned {
|
||||
agent: approval.agent.clone(),
|
||||
ok,
|
||||
note,
|
||||
sha: approval.fetched_sha.clone(),
|
||||
});
|
||||
// Newly spawned container has no claude session yet. Emit
|
||||
// NeedsLogin immediately so the manager prompts the operator
|
||||
// rather than waiting for crash_watch (which would miss it
|
||||
// because the agent appears simultaneously in both prev_needs
|
||||
// and current_needs, making the diff empty on the first tick).
|
||||
if ok {
|
||||
coord.notify_manager(&HelperEvent::NeedsLogin {
|
||||
agent: approval.agent.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
ApprovalKind::Spawn => coord.notify_manager(&HelperEvent::Spawned {
|
||||
agent: approval.agent.clone(),
|
||||
ok,
|
||||
note,
|
||||
sha: approval.fetched_sha.clone(),
|
||||
}),
|
||||
ApprovalKind::ApplyCommit if is_first_spawn => {
|
||||
coord.notify_manager(&HelperEvent::Spawned {
|
||||
agent: approval.agent.clone(),
|
||||
|
|
@ -235,11 +223,6 @@ fn finish_approval(
|
|||
note,
|
||||
sha: approval.fetched_sha.clone(),
|
||||
});
|
||||
if ok {
|
||||
coord.notify_manager(&HelperEvent::NeedsLogin {
|
||||
agent: approval.agent.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
ApprovalKind::ApplyCommit => coord.notify_manager(&HelperEvent::Rebuilt {
|
||||
agent: approval.agent.clone(),
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ pub fn spawn(coord: Arc<Coordinator>) {
|
|||
tokio::spawn(async move {
|
||||
let mut prev_running: HashSet<String> = HashSet::new();
|
||||
let mut prev_logged_in: HashSet<String> = HashSet::new();
|
||||
let mut prev_sub_agents: HashSet<String> = HashSet::new();
|
||||
let mut seeded = false;
|
||||
loop {
|
||||
let raw = lifecycle::list().await.unwrap_or_default();
|
||||
|
|
@ -59,7 +60,13 @@ pub fn spawn(coord: Arc<Coordinator>) {
|
|||
|
||||
if seeded {
|
||||
emit_crash_transitions(&coord, &prev_running, ¤t_running);
|
||||
emit_login_transitions(&coord, &prev_logged_in, ¤t_logged_in, &sub_agents);
|
||||
emit_login_transitions(
|
||||
&coord,
|
||||
&prev_logged_in,
|
||||
¤t_logged_in,
|
||||
&sub_agents,
|
||||
&prev_sub_agents,
|
||||
);
|
||||
}
|
||||
// Periodic container rescan — catches state flips that
|
||||
// happen outside our mutation surface (operator runs
|
||||
|
|
@ -69,6 +76,7 @@ pub fn spawn(coord: Arc<Coordinator>) {
|
|||
coord.rescan_containers_and_emit().await;
|
||||
prev_running = current_running;
|
||||
prev_logged_in = current_logged_in;
|
||||
prev_sub_agents = sub_agents.into_iter().collect();
|
||||
seeded = true;
|
||||
|
||||
tokio::select! {
|
||||
|
|
@ -110,6 +118,7 @@ fn emit_login_transitions(
|
|||
prev: &HashSet<String>,
|
||||
current: &HashSet<String>,
|
||||
sub_agents: &[String],
|
||||
prev_sub_agents: &HashSet<String>,
|
||||
) {
|
||||
for agent in current.difference(prev) {
|
||||
tracing::info!(%agent, "agent logged in");
|
||||
|
|
@ -117,13 +126,16 @@ fn emit_login_transitions(
|
|||
agent: agent.clone(),
|
||||
});
|
||||
}
|
||||
// Only count NeedsLogin transitions for agents that exist and
|
||||
// are *not* logged in — the difference set above already gives
|
||||
// us "was in prev, gone from current" but we also want to fire
|
||||
// for agents that newly appeared as not-logged-in (post-spawn /
|
||||
// post-purge). Treat sub_agents minus current as the
|
||||
// currently-needs-login set; emit when an agent enters it.
|
||||
let prev_needs: HashSet<&str> = sub_agents
|
||||
// Detect transitions into "needs login": an agent that was previously
|
||||
// logged-in goes unsigned (credentials deleted), OR a brand-new agent
|
||||
// appears without a session.
|
||||
//
|
||||
// prev_needs uses prev_sub_agents (the agent set from the last tick) so
|
||||
// that a newly-spawned agent — which does not appear in prev_sub_agents —
|
||||
// is absent from prev_needs even though it's not in prev_logged_in.
|
||||
// Without this, new agents land in both prev_needs and current_needs and
|
||||
// the set difference is empty, silently dropping the event.
|
||||
let prev_needs: HashSet<&str> = prev_sub_agents
|
||||
.iter()
|
||||
.map(String::as_str)
|
||||
.filter(|n| !prev.contains(*n))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue