use argonauts_core::names::{ModelRef, WorkflowId};
use argonauts_core::settings::Settings;
use crate::state::RunState;
use crate::workflow::StepCall;
use crate::workflow::kinds::{find_named, item_task};
pub fn excluded(state: &RunState, settings: &Settings, call: &StepCall) -> Vec<ModelRef> {
let Some(from) = call.step.different_provider_from.as_deref() else {
return Vec::new();
};
let mut workers = if from == "author" {
input_authors(state, call)
} else {
step_workers(state, call.workflow(), from)
};
if workers.is_empty() {
workers.push(settings.crew.main.clone());
}
workers.sort();
workers.dedup();
workers
}
fn input_authors(state: &RunState, call: &StepCall) -> Vec<ModelRef> {
let task = call.item.as_ref().and_then(item_task);
if let Some(worker) = task
.and_then(|task| state.tasks.get(&task))
.and_then(|record| record.worker.clone())
{
return vec![worker];
}
match call.step.input.as_deref() {
Some("diff") => state
.merge
.merged
.iter()
.filter_map(|(task, _)| state.tasks.get(task)?.worker.clone())
.collect(),
Some("goal") => state
.goal
.readings
.iter()
.map(|(_, model, _)| model.clone())
.collect(),
Some("experiments") => state
.plan
.experiment_reports
.iter()
.filter_map(|experiment| state.tasks.get(&experiment.task)?.worker.clone())
.collect(),
Some("plan") | None => match state.plan.chosen() {
Some(chosen) => vec![chosen.worker.clone()],
None => state
.plan
.latest()
.iter()
.map(|draft| draft.worker.clone())
.collect(),
},
Some(name) => step_workers(state, call.workflow(), name),
}
}
pub fn step_workers(state: &RunState, workflow: &WorkflowId, name: &str) -> Vec<ModelRef> {
let Some((phase, path)) = state
.workflows
.by_id
.get(workflow)
.and_then(|record| find_named(&record.workflow, name))
else {
return Vec::new();
};
state
.sessions
.by_key
.values()
.filter(|record| {
record.started.workflow_step.as_ref().is_some_and(|at| {
at.workflow == *workflow && at.phase == phase && at.path.starts_with(&path)
})
})
.map(|record| record.started.worker.clone())
.collect()
}