Command center: edit brain sections inline from the cards
ci / gates (push) Failing after 11s
ci / rust (push) Has been skipped
ci / sandbox-k8s (push) Has been skipped
ci / frontend (push) Has been skipped
ci / e2e (push) Has been skipped

Add PATCH /api/claws/{id}/brain (edit_brain): writes any of system_prompt / agent_md
/ persona / skills_md into the claw's .brain (best-effort) + persists system_prompt
to Postgres (authoritative) + commits a ClawSync revision.

Frontend: a reusable EditableSection (pencil → textarea → Save/Cancel → PATCH →
re-fetch brain). The SYSTEM PROMPT, HOW I OPERATE (AGENTS.md), and PERSONALITY cards
in the command center are now editable inline; saving writes back to the mapped
brain section. AGENTS.md card now always shows (so it can be authored when empty).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-26 13:30:58 -07:00
co-authored by Claude Opus 4.8
parent 9fca3f6676
commit 89c147b742
4 changed files with 112 additions and 12 deletions
+47
View File
@@ -218,6 +218,53 @@ fn load_brain(agent: &Agent, skills: &[(String, String)]) -> ClawBrainResponse {
}
}
/// Edit one or more brain sections from the command-center cards.
#[derive(Deserialize)]
pub struct BrainEdit {
pub system_prompt: Option<String>,
pub agent_md: Option<String>,
pub persona: Option<String>,
pub skills_md: Option<String>,
}
/// `PATCH /api/claws/{id}/brain` — edit individual `.brain` sections inline from
/// the dashboard cards. Each present field is written to the claw's brain;
/// `system_prompt` is also persisted to Postgres (authoritative). Commits a
/// ClawSync revision so every edit is reversible.
pub async fn edit_brain(
State(state): State<AppState>,
Authed(user): Authed,
Path(id): Path<AgentId>,
Json(req): Json<BrainEdit>,
) -> Result<Json<Value>, ApiError> {
let agent = workspace_agent(&state, &user, id).await?;
// system_prompt stays authoritative in Postgres.
if let Some(sp) = req.system_prompt.as_ref() {
let _ = cm_db::repo::agents::update_profile(
&state.pool, agent.id, None, None, Some(sp.trim()), None, None, None,
)
.await;
}
// Mirror every edited section into the `.brain` (best-effort) + snapshot.
let path = brain_dir().join(format!("claw_{}.h5", agent.id));
if let Ok(mut brain) = cm_brain::ClawBrain::open_or_create(&path, &agent.id.to_string()) {
if let Some(sp) = req.system_prompt.as_ref() {
let _ = brain.set_system_prompt(sp);
}
if let Some(a) = req.agent_md.as_ref() {
let _ = brain.set_agent_md(a);
}
if let Some(p) = req.persona.as_ref() {
let _ = brain.set_personality(p);
}
if let Some(s) = req.skills_md.as_ref() {
let _ = brain.set_skills_md(s);
}
let _ = brain.commit(Some("edited from dashboard"));
}
Ok(Json(serde_json::json!({ "ok": true })))
}
pub async fn brain(
State(state): State<AppState>,
Authed(user): Authed,