use crate::caveats::Caveats;
use async_trait::async_trait;
use serde_json::Value;
#[async_trait]
pub trait CrewRunner: Send + Sync {
async fn dispatch(&self, op: &str, args: &Value, caveats: &Caveats) -> Result<String, String>;
}
pub fn compose_roster_tool_definition() -> Value {
serde_json::json!({
"type": "function",
"function": {
"name": "compose_roster",
"description": "Survey the live models/backends and PROPOSE a crew roster \
(which model fills planner/navigator/triage, and whether to \
run as a crew, a team, or a decorrelated panel) for the human \
to approve. Returns the proposal with a rationale per pick. \
Does NOT run anything — propose, then the human approves.",
"parameters": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": ["crew", "team", "panel"],
"description": "crew = roles divide one task; team = a lead \
decomposes a goal then a crew runs each subtask; \
panel = N decorrelated voices on the same task."
},
"goal": {
"type": "string",
"description": "Optional: the goal/plan the roster is being composed for (context)."
}
},
"required": ["mode"]
}
}
})
}
pub fn crew_tool_definition() -> Value {
serde_json::json!({
"type": "function",
"function": {
"name": "crew",
"description": "Dispatch a crew on a task UNDER YOUR OVERSIGHT: it edits an \
isolated workspace, runs the verification, and returns the diff \
+ status for you to review and accept or re-dispatch. Compose a \
roster first (compose_roster) or name a saved crew. Crews run \
under your authority met with the crew clamp — they can never \
exceed your authority (their permissions are <= yours).",
"parameters": {
"type": "object",
"properties": {
"task": {
"type": "string",
"description": "The single task (one plan step) for the crew to land."
},
"mode": {
"type": "string",
"enum": ["crew", "team"],
"description": "crew (default) runs one task; team decomposes the \
task as a goal and runs a crew per subtask."
},
"crew": {
"type": "string",
"description": "Optional: the name of a saved [crews.<name>] roster to field."
},
"verify": {
"type": "string",
"description": "Optional: the shell command that verifies this task is done."
}
},
"required": ["task"]
}
}
})
}