diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index bbbc35d..3a71857 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -431,9 +431,18 @@ export async function reviewCheckpoint(checkpointId: string): Promise { - return requestV2(`/repos/${repoId}`, { method: 'DELETE' }); +/** + * Delete a space and cascade to all its checkpoints, sessions, and turns. + * The backend refuses with 409 unless force=true is passed for a space that + * still holds checkpoints, so callers must confirm with the user first, then + * pass { force: true }. + */ +export async function deleteRepo( + repoId: string, + opts?: { force?: boolean }, +): Promise { + const qs = opts?.force ? '?force=true' : ''; + return requestV2(`/repos/${repoId}${qs}`, { method: 'DELETE' }); } /** diff --git a/frontend/src/pages/WorkspaceOverviewPage.tsx b/frontend/src/pages/WorkspaceOverviewPage.tsx index aa19270..981f471 100644 --- a/frontend/src/pages/WorkspaceOverviewPage.tsx +++ b/frontend/src/pages/WorkspaceOverviewPage.tsx @@ -430,7 +430,10 @@ export function WorkspaceOverviewPage() { body="This will permanently delete the space, all of its checkpoints, sessions, and turns. This cannot be undone." onClose={() => setDeleteTarget(null)} onConfirm={async () => { - await deleteRepo(deleteTarget.id); + // force=true: the ConfirmDeleteModal above is the user's + // explicit confirmation, which the backend's non-empty + // delete guard requires. + await deleteRepo(deleteTarget.id, { force: true }); setDeleteTarget(null); await refreshWorkspace(); }}