use crate::capability::CapabilityRef;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BuiltInHarnessPreset {
Base,
Conversation,
WorkerBase,
Worker,
}
impl BuiltInHarnessPreset {
pub const fn name(self) -> &'static str {
match self {
Self::Base => "base",
Self::Conversation => "conversation",
Self::WorkerBase => "worker-base",
Self::Worker => "worker",
}
}
pub const fn parent(self) -> Option<Self> {
match self {
Self::Base => None,
Self::Conversation => Some(Self::Base),
Self::WorkerBase => Some(Self::Conversation),
Self::Worker => Some(Self::WorkerBase),
}
}
pub fn local_capabilities(self) -> Vec<CapabilityRef> {
match self {
Self::Base => vec![],
Self::Conversation => vec![
CapabilityRef::with_config(
"compaction",
serde_json::json!({
"strategy": "auto", "proactive": true, "budget_percent": 0.85
}),
),
CapabilityRef::new("error_disclosure"),
CapabilityRef::new("tool_call_repair"),
CapabilityRef::new("loop_detection"),
],
Self::WorkerBase => vec![
CapabilityRef::new("session_file_system"),
CapabilityRef::new("bashkit_shell"),
CapabilityRef::new("agent_instructions"),
CapabilityRef::new("session"),
CapabilityRef::new("tool_output_persistence"),
CapabilityRef::new("tool_output_distillation"),
CapabilityRef::with_config(
"parallel_tool_calls",
serde_json::json!({"mode": "prefer"}),
),
CapabilityRef::new("soft_approval"),
],
Self::Worker => vec![
CapabilityRef::new("skills"),
CapabilityRef::new("infinity_context"),
CapabilityRef::new("auto_tool_search"),
CapabilityRef::new("budgeting"),
CapabilityRef::new("self_budget"),
CapabilityRef::new("stateless_todo_list"),
CapabilityRef::new("subagents"),
CapabilityRef::new("session_tasks"),
],
}
}
pub fn effective_capabilities(self) -> Vec<CapabilityRef> {
let mut capabilities = self
.parent()
.map(Self::effective_capabilities)
.unwrap_or_default();
capabilities.extend(self.local_capabilities());
capabilities
}
}
pub const GENERIC_HARNESS_NAME: &str = "generic";
pub fn generic_capabilities() -> Vec<CapabilityRef> {
vec![
CapabilityRef::new("human_intent"),
CapabilityRef::new("session_file_system"),
CapabilityRef::new("bashkit_shell"),
CapabilityRef::with_config(
"web_fetch",
serde_json::json!({"enable_file_download": true}),
),
CapabilityRef::new("session_storage"),
CapabilityRef::new("session"),
CapabilityRef::new("session_schedule"),
CapabilityRef::new("btw"),
CapabilityRef::new("agent_instructions"),
CapabilityRef::new("skills"),
CapabilityRef::new("infinity_context"),
CapabilityRef::new("auto_tool_search"),
CapabilityRef::new("budgeting"),
CapabilityRef::new("self_budget"),
CapabilityRef::new("loop_detection"),
CapabilityRef::with_config("parallel_tool_calls", serde_json::json!({"mode": "prefer"})),
CapabilityRef::with_config("error_disclosure", serde_json::json!({"mode": "detailed"})),
CapabilityRef::new("message_metadata"),
CapabilityRef::with_config(
"compaction",
serde_json::json!({
"strategy": "auto",
"proactive": true,
"budget_percent": 0.85
}),
),
CapabilityRef::new("tool_output_persistence"),
CapabilityRef::new("tool_output_distillation"),
CapabilityRef::new("citation_retrieval"),
CapabilityRef::new("citation_verification"),
CapabilityRef::new("ask_user"),
CapabilityRef::new("soft_approval"),
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn levels_have_distinct_effective_surfaces() {
use BuiltInHarnessPreset::*;
assert!(Base.effective_capabilities().is_empty());
for preset in [Conversation, WorkerBase, Worker] {
let caps = preset.effective_capabilities();
let ids: Vec<_> = caps.iter().map(CapabilityRef::capability_id).collect();
let unique: std::collections::HashSet<_> = ids.iter().collect();
assert_eq!(ids.len(), unique.len());
assert_eq!(ids.contains(&"bashkit_shell"), preset != Conversation);
assert_eq!(ids.contains(&"subagents"), preset == Worker);
assert_eq!(ids.contains(&"session_tasks"), preset == Worker);
for opt_in in [
"web_fetch",
"session_storage",
"session_schedule",
"memory",
"citation_retrieval",
"ask_user",
] {
assert!(
!ids.contains(&opt_in),
"{opt_in} leaked into {}",
preset.name()
);
}
}
assert!(
!generic_capabilities()
.iter()
.any(|cap| cap.capability_id() == "subagents")
);
}
#[test]
fn generic_carries_no_duplicate_capability() {
let capabilities = generic_capabilities();
let mut ids: Vec<_> = capabilities
.iter()
.map(|capability| capability.capability_id().to_string())
.collect();
ids.sort();
let count = ids.len();
ids.dedup();
assert_eq!(count, ids.len(), "a capability is listed twice");
}
#[test]
fn generic_configs_are_objects() {
for capability in generic_capabilities() {
assert!(
capability.config_value().is_object(),
"{} carries a non-object config",
capability.capability_id()
);
}
}
#[test]
fn generic_names_the_shell_and_filesystem_it_promises() {
let ids: Vec<_> = generic_capabilities()
.iter()
.map(|capability| capability.capability_id().to_string())
.collect();
for expected in ["session_file_system", "bashkit_shell", "web_fetch"] {
assert!(ids.iter().any(|id| id == expected), "missing {expected}");
}
}
}