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:
co-authored by
Claude Opus 4.8
parent
9f266d5806
commit
34f744734b
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user