fix(agents): a soft-deleted agent could never be purged
Clearing the fleet's four leftover agents returned 404 on every one. They had
been soft-deleted back in June — correctly invisible in the UI ever since — and
`agents::get` filters `deleted_at IS NULL`, so `workspace_agent` could not find
them. Every route uses it, including `batch-delete`, the one that exists to
HARD-purge. So a soft-deleted agent was unreachable from the application
entirely and its row stayed forever.
`get_any` sees them, and only the purge path uses it: hiding soft-deleted rows
is right for every read, and wrong for the one operation whose whole job is
removing them. Written with `query_as` rather than the checked macro so it does
not force an offline-cache regeneration on every machine that builds this.
`fleet-reset.sh` now uses `batch-delete` for agents rather than
`DELETE /api/claws/{id}`. The latter is a SOFT delete, so pointing a reset
script at it would have quietly added to the pile it was meant to clear.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
16cfc29074
commit
f27d2605eb
@@ -26,6 +26,19 @@ pub(crate) async fn workspace_agent(
|
||||
Ok(agent)
|
||||
}
|
||||
|
||||
/// As [`workspace_agent`], but sees soft-deleted agents too. PURGE ONLY.
|
||||
pub(crate) async fn workspace_agent_any(
|
||||
state: &AppState,
|
||||
user: &cm_auth::AuthedUser,
|
||||
agent_id: AgentId,
|
||||
) -> Result<Agent, ApiError> {
|
||||
let agent = cm_db::repo::agents::get_any(&state.pool, agent_id).await?;
|
||||
if agent.workspace_id != user.workspace_id {
|
||||
return Err(ApiError::NotFound);
|
||||
}
|
||||
Ok(agent)
|
||||
}
|
||||
|
||||
/// `GET /api/claws/{id}/runtime-config` — the claw's model + §15 sandbox facts
|
||||
/// (for the claw card / anatomy view's model badge).
|
||||
#[derive(Serialize)]
|
||||
@@ -1289,7 +1302,12 @@ pub async fn batch_delete(
|
||||
let mut done = 0usize;
|
||||
for id in agent_ids {
|
||||
let base = 100 * done / total;
|
||||
let agent = match workspace_agent(&state, &user, id).await {
|
||||
// `workspace_agent_any`, not `workspace_agent`: a purge has to be
|
||||
// able to see the rows it exists to remove. The soft-delete path
|
||||
// correctly hides them from every read, which also hid them from
|
||||
// the only route that could reap them — four soft-deleted agents
|
||||
// from June were unreachable from the application entirely.
|
||||
let agent = match workspace_agent_any(&state, &user, id).await {
|
||||
Ok(a) => a,
|
||||
Err(_) => { yield sse(json!({"stage":"skip","pct":base,"label":format!("{id}: not found or no access")})); done += 1; continue; }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user