use crate::agent::AgentId;
use crate::channel::Channel;
use crate::error::Result;
use crate::message::{Message, MessageType};
use crate::task::{Task, TaskId};
use crate::town::Town;
#[derive(Debug, Clone)]
pub struct BacklogItem {
pub task_id: TaskId,
pub description: String,
pub tags: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct AddBacklogResult {
pub task_id: TaskId,
pub description: String,
}
#[derive(Debug, Clone)]
pub struct ClaimResult {
pub task_id: TaskId,
pub agent_id: AgentId,
pub agent_name: String,
}
pub struct BacklogService;
impl BacklogService {
pub async fn add(
channel: &Channel,
description: &str,
tags: Option<Vec<String>>,
) -> Result<AddBacklogResult> {
let mut task = Task::new(description);
if let Some(tag_list) = tags {
task = task.with_tags(tag_list);
}
let task_id = task.id;
channel.set_task(&task).await?;
channel.backlog_push(task_id).await?;
Ok(AddBacklogResult {
task_id,
description: description.to_string(),
})
}
pub async fn list(channel: &Channel) -> Result<Vec<BacklogItem>> {
let task_ids = channel.backlog_list().await?;
let mut items = Vec::new();
for task_id in task_ids {
if let Ok(Some(task)) = channel.get_task(task_id).await {
items.push(BacklogItem {
task_id,
description: task.description,
tags: task.tags,
});
} else {
items.push(BacklogItem {
task_id,
description: "(task record not found)".to_string(),
tags: Vec::new(),
});
}
}
Ok(items)
}
#[allow(dead_code)]
pub async fn len(channel: &Channel) -> Result<usize> {
channel.backlog_len().await
}
pub async fn claim(town: &Town, task_id: TaskId, agent_name: &str) -> Result<ClaimResult> {
let channel = town.channel();
let removed = channel.backlog_remove(task_id).await?;
if !removed {
return Err(crate::error::Error::TaskNotFound(format!(
"Task {} not in backlog",
task_id
)));
}
let agent_handle = town.agent(agent_name).await?;
let agent_id = agent_handle.id();
if let Some(mut task) = channel.get_task(task_id).await? {
task.assign(agent_id);
channel.set_task(&task).await?;
}
let msg = Message::new(
AgentId::supervisor(),
agent_id,
MessageType::TaskAssign {
task_id: task_id.to_string(),
},
);
channel.send(&msg).await?;
Ok(ClaimResult {
task_id,
agent_id,
agent_name: agent_name.to_string(),
})
}
pub async fn remove(channel: &Channel, task_id: TaskId) -> Result<bool> {
let removed = channel.backlog_remove(task_id).await?;
if removed {
channel.delete_task(task_id).await?;
}
Ok(removed)
}
pub async fn assign_all(town: &Town, agent_name: &str) -> Result<Vec<ClaimResult>> {
let channel = town.channel();
let agent_handle = town.agent(agent_name).await?;
let agent_id = agent_handle.id();
let mut results = Vec::new();
while let Some(task_id) = channel.backlog_pop().await? {
if let Some(mut task) = channel.get_task(task_id).await? {
task.assign(agent_id);
channel.set_task(&task).await?;
let msg = Message::new(
AgentId::supervisor(),
agent_id,
MessageType::TaskAssign {
task_id: task_id.to_string(),
},
);
channel.send(&msg).await?;
results.push(ClaimResult {
task_id,
agent_id,
agent_name: agent_name.to_string(),
});
}
}
Ok(results)
}
}