use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Arc;
use super::session::TaskSource;
#[derive(Debug, Clone)]
pub struct PlannedTask {
pub source: TaskSource,
pub source_name: String,
pub goal: String,
pub mount_paths: Vec<PathBuf>,
}
pub struct WorkPlanner {
skills: Arc<crate::skill::SkillManager>,
projects: Option<Arc<crate::project::ProjectManager>>,
}
impl WorkPlanner {
pub fn new(
skills: Arc<crate::skill::SkillManager>,
projects: Option<Arc<crate::project::ProjectManager>>,
) -> Self {
Self { skills, projects }
}
pub async fn next_task(&self, done_goals: &HashSet<String>) -> Option<PlannedTask> {
for entry in self.skills.list_skills().await {
let autonomous = entry
.metadata
.as_ref()
.map(|m| m.autonomous)
.unwrap_or(false);
if !autonomous {
continue;
}
let goal = format!(
"[Skill: {}] {}. Perform this skill's routine work autonomously and \
summarize the outcome. Do not make destructive changes or run deploys.",
entry.skill.name, entry.skill.description
);
if done_goals.contains(&goal) {
continue;
}
return Some(PlannedTask {
source: TaskSource::Skill,
source_name: entry.skill.name.clone(),
goal,
mount_paths: Vec::new(),
});
}
if let Some(pm) = &self.projects {
for proj in pm.list_projects() {
if proj.paths.is_empty() {
continue;
}
let goal = format!(
"[Project: {}] Review the recent state of this project: summarize open \
work, recent changes, and any TODOs/FIXMEs. Read-only — do not modify \
files or run deploys.",
proj.name
);
if done_goals.contains(&goal) {
continue;
}
return Some(PlannedTask {
source: TaskSource::Project,
source_name: proj.name.clone(),
goal,
mount_paths: proj.paths.clone(),
});
}
}
None
}
}