feat: recover detached agent runs and interactions

This commit is contained in:
boos
2026-07-14 07:17:00 +08:00
parent cf73250999
commit 9fe770ad26
5 changed files with 259 additions and 8 deletions
+31
View File
@@ -258,6 +258,21 @@ impl InteractionBroker {
self.entries.lock().await.len()
}
/// Return a snapshot of unresolved interactions for one run. The full
/// binding must match, so callers cannot inspect another actor's prompts.
pub async fn pending_for_binding(
&self,
binding: &InteractionBinding,
) -> Vec<InteractionRequest> {
self.entries
.lock()
.await
.values()
.filter(|entry| &entry.request.binding == binding)
.map(|entry| entry.request.clone())
.collect()
}
async fn expire(&self, interaction_id: &str, generation: uuid::Uuid) -> bool {
let mut entries = self.entries.lock().await;
let matches_generation = entries
@@ -470,4 +485,20 @@ mod tests {
Err(BrokerError::Cancelled(_))
));
}
#[tokio::test]
async fn pending_snapshot_is_scoped_to_the_full_binding() {
let broker = InteractionBroker::default();
let pending = broker
.register(request("approval-6"), CancellationToken::new())
.await
.unwrap();
assert_eq!(broker.pending_for_binding(&binding()).await.len(), 1);
assert!(broker
.pending_for_binding(&InteractionBinding::new("other", "session", "run"))
.await
.is_empty());
broker.cancel_run(&binding()).await;
assert!(matches!(pending.wait().await, Err(BrokerError::Cancelled(_))));
}
}