master planner: wire user-locked topology_kind through chat + scaffold
Frontend: send topologyKind to /api/planner/chat so the planner's user prompt gets a USER-LOCKED TOPOLOGY block telling Opus to use it verbatim. On buildTeam, override proposal.topology_kind with the user's pick (belt-and-braces — if the planner ignored the lock, we still ship the right shape). Proposal chip renders the effective kind in a lavender tint when it was overridden, with a hover title showing what was replaced. Backend PlannerChatRequest gains an optional topology_kind. Empty / absent = planner picks. Not honored for 'swarm' mode (swarm planner doesn't take a topology kind).
This commit is contained in:
@@ -54,6 +54,11 @@ pub struct PlannerChatRequest {
|
||||
/// Deploy mode: specialists | team | swarm | scheduled | triggered (default specialists).
|
||||
#[serde(default)]
|
||||
pub mode: String,
|
||||
/// User-locked topology from the gallery. When set the planner is told to
|
||||
/// use this kind verbatim (no rewrite). Ignored for `swarm` mode (the swarm
|
||||
/// planner doesn't take a topology kind).
|
||||
#[serde(default)]
|
||||
pub topology_kind: Option<String>,
|
||||
}
|
||||
|
||||
const SPECIALISTS_NOTE: &str = "\n\nMODE: Specialists. Propose a TIGHTLY-SCOPED group of 2 or 3 DOMAIN \
|
||||
@@ -113,7 +118,15 @@ pub async fn planner_chat(
|
||||
let convo = body.messages.iter()
|
||||
.map(|m| format!("{}: {}", if m.role == "user" { "USER" } else { "PLANNER" }, m.content))
|
||||
.collect::<Vec<_>>().join("\n\n");
|
||||
let user_prompt = format!("{hierarchy}\n\n=== CONVERSATION ===\n{convo}\n\nRespond now (JSON only).");
|
||||
let topology_lock = match body.topology_kind.as_deref() {
|
||||
Some(k) if !k.is_empty() && body.mode != "swarm" => format!(
|
||||
"\n\n=== USER-LOCKED TOPOLOGY ===\nThe user has selected topology_kind='{k}' from the gallery. \
|
||||
Use this kind verbatim in the proposal; do NOT choose a different one. Tailor the roles + \
|
||||
member count to work well within this shape."
|
||||
),
|
||||
_ => String::new(),
|
||||
};
|
||||
let user_prompt = format!("{hierarchy}{topology_lock}\n\n=== CONVERSATION ===\n{convo}\n\nRespond now (JSON only).");
|
||||
let system = planner_system_for(&body.mode);
|
||||
let raw = match runtime.complete(&system, &user_prompt, "claude-opus-4-8", 8000, true).await {
|
||||
Ok(t) => t,
|
||||
|
||||
Reference in New Issue
Block a user