fix(runtime): isolate agent state by project (#101)

This commit is contained in:
2026-07-25 22:14:02 +02:00
parent 6a87c4635f
commit 6e98fd89f7
52 changed files with 1894 additions and 805 deletions

View File

@ -10,7 +10,7 @@ use std::sync::Arc;
use async_trait::async_trait;
use domain::background_task::{BackgroundTask, BackgroundTaskResult};
use domain::events::DomainEvent;
use domain::ids::AgentId;
use domain::ids::{AgentId, RuntimeAgentKey};
use domain::inbox::{AgentInbox, InboxItem, InboxItemKind, InboxSource};
use domain::input::InputMediator;
use domain::mailbox::{AgentMailbox, Ticket};
@ -90,25 +90,26 @@ impl AgentWakeService {
agent: AgentId,
reason: WakeReason,
) -> Result<(), WakeError> {
let key = RuntimeAgentKey::new(project.id, agent);
self.publish(DomainEvent::AgentWakeScheduled {
project_id: project.id,
agent_id: agent,
});
if self.input.busy_state(agent).is_busy() {
if self.input.busy_state(key).is_busy() {
return Err(WakeError::AgentBusy { agent_id: agent });
}
let Some(item) = self.inbox.dequeue_next(agent) else {
let Some(item) = self.inbox.dequeue_next(key) else {
return Ok(());
};
let delivery = self.delivery_from_item(item, &reason).await?;
let ticket = Ticket::new(delivery.ticket_id, "IdeA", delivery.prompt.clone());
let _pending = self.input.enqueue_silent(agent, ticket);
let _pending = self.input.enqueue_silent(key, ticket);
let guard = WakeTurnGuard::new(
Arc::clone(&self.input),
Arc::clone(&self.mailbox),
agent,
key,
delivery.ticket_id,
);
@ -133,12 +134,12 @@ impl AgentWakeService {
owner_agent_id: agent,
});
}
drain_reply_stream_with_readiness(stream, self.input.as_ref(), agent)
drain_reply_stream_with_readiness(stream, self.input.as_ref(), key)
.await
.map_err(|err| WakeError::Session(err.to_string()))?;
self.mailbox.cancel_head(agent, delivery.ticket_id);
self.input.mark_idle(agent);
self.mailbox.cancel_head(key, delivery.ticket_id);
self.input.mark_idle(key);
guard.disarm();
Ok(())
}
@ -220,7 +221,7 @@ struct WakeDelivery {
struct WakeTurnGuard {
input: Arc<dyn InputMediator>,
mailbox: Arc<dyn AgentMailbox>,
agent: AgentId,
agent: RuntimeAgentKey,
ticket: domain::mailbox::TicketId,
armed: bool,
}
@ -229,7 +230,7 @@ impl WakeTurnGuard {
fn new(
input: Arc<dyn InputMediator>,
mailbox: Arc<dyn AgentMailbox>,
agent: AgentId,
agent: RuntimeAgentKey,
ticket: domain::mailbox::TicketId,
) -> Self {
Self {