Large World graph, agent platform, brain stack & dashboard rebuild

Frontend
- Large World: collapse org/company/team tiers into one expandable React Flow
  hierarchy (WorldFlow) with per-click expand, persisted node positions, a
  compact tree sidebar, wrench multi-select delete across levels, and a sized
  right slide-out (phone/tablet/full) showing an agent summary + drill button.
- Agent page: GitHub-style animated contribution grid (VitalsCard), collapsible
  System Prompt + Personality cards, restructured anatomy cards, bigger avatar
  with name/title header row, Markdown/JSON-aware rendering, brain registry +
  history, avatar generate/upload.
- User-icon menu (Infrastructure/Brains/Tools/Profile/Credits) + ToolPanel;
  Master Planner deploy wizard (Specialists/Swarm/Scheduled/Triggered);
  Team Runs view; reap-progress modal; dashboard is the single live interface.

Backend
- cm-brain crate (.brain as the agent definition) + brain apply/history.
- Hard-purge reap (FK-ordered) + sandbox release + SSE batch-delete.
- Swarm self-verifying loop, mode-aware planner, web.search tool, webhooks
  (migration 0013), org/company/team delete endpoints, scheduler sweeps.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-22 23:21:54 -07:00
co-authored by Claude Opus 4.8
parent 9f266d5806
commit 34f744734b
123 changed files with 9591 additions and 1098 deletions
+86
View File
@@ -256,3 +256,89 @@ pub async fn soft_delete(pool: &PgPool, agent_id: AgentId) -> Result<(), DbError
}
Ok(())
}
/// Counts of the rows reaped by [`hard_purge`], for the progress summary.
#[derive(Debug, Default, Clone, Copy)]
pub struct PurgeCounts {
pub sessions: u64,
pub approvals: u64,
pub connections: u64,
pub files: u64,
}
/// Hard-delete an agent and everything that references it, in FK-dependency
/// order, in one transaction. Auto-CASCADE handles access_policies,
/// installed_skills, routines(+routine_runs) and team_members; the non-cascade
/// references (chat history, approvals, threads, connections, queued mail, file
/// drives, usage) are cleared first so the final `DELETE FROM agents` succeeds.
/// Only the immutable `audit_log` survives. Returns NotFound if the agent is gone.
pub async fn hard_purge(pool: &PgPool, agent_id: AgentId) -> Result<PurgeCounts, DbError> {
let aid = agent_id.as_uuid();
let mut tx = pool.begin().await?;
let mut c = PurgeCounts::default();
// Chat history: steps → messages → agent_runs → sessions (none cascade).
sqlx::query(
"DELETE FROM steps WHERE message_id IN \
(SELECT m.id FROM messages m JOIN sessions s ON m.session_id = s.id WHERE s.agent_id = $1)",
)
.bind(aid)
.execute(&mut *tx)
.await?;
sqlx::query("DELETE FROM messages WHERE session_id IN (SELECT id FROM sessions WHERE agent_id = $1)")
.bind(aid)
.execute(&mut *tx)
.await?;
sqlx::query("DELETE FROM agent_runs WHERE session_id IN (SELECT id FROM sessions WHERE agent_id = $1)")
.bind(aid)
.execute(&mut *tx)
.await?;
c.sessions = sqlx::query("DELETE FROM sessions WHERE agent_id = $1")
.bind(aid)
.execute(&mut *tx)
.await?
.rows_affected();
// Approvals: execution_grants → approvals.
sqlx::query(
"DELETE FROM execution_grants WHERE approval_id IN \
(SELECT id FROM approvals WHERE requested_by_agent = $1)",
)
.bind(aid)
.execute(&mut *tx)
.await?;
c.approvals = sqlx::query("DELETE FROM approvals WHERE requested_by_agent = $1")
.bind(aid)
.execute(&mut *tx)
.await?
.rows_affected();
// Inter-agent threads, queued mail, oauth flows.
sqlx::query("DELETE FROM thread_messages WHERE from_agent = $1").bind(aid).execute(&mut *tx).await?;
sqlx::query("DELETE FROM thread_participants WHERE agent_id = $1").bind(aid).execute(&mut *tx).await?;
sqlx::query("DELETE FROM outbox WHERE agent_id = $1").bind(aid).execute(&mut *tx).await?;
sqlx::query("DELETE FROM oauth_states WHERE agent_id = $1").bind(aid).execute(&mut *tx).await?;
c.connections = sqlx::query("DELETE FROM app_connections WHERE agent_id = $1")
.bind(aid)
.execute(&mut *tx)
.await?
.rows_affected();
c.files = sqlx::query("DELETE FROM file_nodes WHERE agent_id = $1")
.bind(aid)
.execute(&mut *tx)
.await?
.rows_affected();
sqlx::query("DELETE FROM usage_events WHERE agent_id = $1").bind(aid).execute(&mut *tx).await?;
// Finally the agent itself (cascades the rest).
let n = sqlx::query("DELETE FROM agents WHERE id = $1")
.bind(aid)
.execute(&mut *tx)
.await?
.rows_affected();
if n == 0 {
return Err(DbError::NotFound);
}
tx.commit().await?;
Ok(c)
}
+39
View File
@@ -61,6 +61,45 @@ pub async fn insert_company(
Ok(())
}
/// Rebuild a company's topology (kind + graph) in place; node→team bindings
/// (keyed off stable node ids `n0..`) are left untouched. Non-macro query.
pub async fn set_topology(
pool: &PgPool,
id: Uuid,
workspace_id: WorkspaceId,
kind: &str,
graph: &Value,
) -> Result<(), DbError> {
let res = sqlx::query("UPDATE companies SET kind = $3, graph = $4 WHERE id = $1 AND workspace_id = $2")
.bind(id)
.bind(workspace_id.as_uuid())
.bind(kind)
.bind(graph)
.execute(pool)
.await?;
if res.rows_affected() == 0 {
return Err(DbError::NotFound);
}
Ok(())
}
/// Delete a company and its node→team bindings (teams themselves remain).
pub async fn delete_company(pool: &PgPool, id: Uuid, workspace_id: WorkspaceId) -> Result<(), DbError> {
sqlx::query("DELETE FROM company_teams WHERE company_id = $1")
.bind(id)
.execute(pool)
.await?;
let res = sqlx::query("DELETE FROM companies WHERE id = $1 AND workspace_id = $2")
.bind(id)
.bind(workspace_id.as_uuid())
.execute(pool)
.await?;
if res.rows_affected() == 0 {
return Err(DbError::NotFound);
}
Ok(())
}
/// Bind a team to a topology node within a company.
pub async fn add_team(
pool: &PgPool,
+18
View File
@@ -146,3 +146,21 @@ pub async fn companies_for_org(pool: &PgPool, org_id: Uuid) -> Result<Vec<OrgCom
})
.collect())
}
/// Delete an org. Structural only: the `org_companies` links are removed
/// (cascade) so the companies survive, just ungrouped from this org.
pub async fn delete_org(pool: &PgPool, id: Uuid, workspace_id: WorkspaceId) -> Result<(), DbError> {
sqlx::query("DELETE FROM org_companies WHERE org_id = $1")
.bind(id)
.execute(pool)
.await?;
let res = sqlx::query("DELETE FROM orgs WHERE id = $1 AND workspace_id = $2")
.bind(id)
.bind(workspace_id.as_uuid())
.execute(pool)
.await?;
if res.rows_affected() == 0 {
return Err(DbError::NotFound);
}
Ok(())
}
+40
View File
@@ -59,6 +59,46 @@ pub async fn insert_team(
Ok(())
}
/// Rebuild a team's topology (kind + graph) in place; node→claw bindings (which
/// key off stable node ids `n0..`) are left untouched. Non-macro query so it
/// needs no offline sqlx cache entry.
pub async fn set_topology(
pool: &PgPool,
id: Uuid,
workspace_id: WorkspaceId,
kind: &str,
graph: &Value,
) -> Result<(), DbError> {
let res = sqlx::query("UPDATE teams SET kind = $3, graph = $4 WHERE id = $1 AND workspace_id = $2")
.bind(id)
.bind(workspace_id.as_uuid())
.bind(kind)
.bind(graph)
.execute(pool)
.await?;
if res.rows_affected() == 0 {
return Err(DbError::NotFound);
}
Ok(())
}
/// Delete a team and its node→claw bindings.
pub async fn delete_team(pool: &PgPool, id: Uuid, workspace_id: WorkspaceId) -> Result<(), DbError> {
sqlx::query("DELETE FROM team_members WHERE team_id = $1")
.bind(id)
.execute(pool)
.await?;
let res = sqlx::query("DELETE FROM teams WHERE id = $1 AND workspace_id = $2")
.bind(id)
.bind(workspace_id.as_uuid())
.execute(pool)
.await?;
if res.rows_affected() == 0 {
return Err(DbError::NotFound);
}
Ok(())
}
/// Bind a claw to a topology node within a team.
pub async fn add_member(
pool: &PgPool,