Files
cobble/src/functions/backend/db/tasks/purge-task-media.ts
T
tbenandClaude Opus 5.5 864dcce30a Scope workspace tasks to the bot that has them
A workspace's task now carries the bot that has it there (bot_id with
workspace_id), or none while it's shared. A bot reaches its own list and,
in its workspaces, its own tasks plus the shared ones; a workspace admin
every task there. Bots create workspace tasks for themselves by default,
take a shared one by starting it, and hand-overs record the new bot.
Removing or deleting a bot makes its workspace tasks shared again. The
conversation's Tasks modal shows that bot's tasks in the workspace.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 19:19:01 +01:00

35 lines
1.3 KiB
TypeScript

import BunSQLite from "@moduletrace/bun-sqlite";
import type { BUN_SQLITE_COBBLE_TASK_MEDIA } from "@/db/types/db";
type Params = {
/**
* A bot's own list (not what it has in workspaces), or a workspace's.
*/
bot_id?: number | string | null;
workspace_id?: number | string | null;
};
/**
* The bytes a bot's or workspace's tasks filed that no folder owns (a chat
* upload linked to a task). Read before the bot or workspace is deleted:
* the tasks and their links cascade, and nothing else would ever clean
* those files up. A bot file is left alone: its folder is its home.
*/
export async function grabTaskMediaIds({ bot_id, workspace_id }: Params): Promise<number[]> {
const column = workspace_id ? "workspace_id" : "bot_id";
const owner = workspace_id || bot_id;
if (!owner) return [];
const links = (
await BunSQLite.sql<BUN_SQLITE_COBBLE_TASK_MEDIA>({
sql: `SELECT tm.media_id FROM task_media tm
JOIN tasks t ON t.id = tm.task_id
WHERE t.${column} = ? ${workspace_id ? "" : "AND t.workspace_id IS NULL"} AND tm.bot_file_id IS NULL`,
values: [Number(owner)],
})
).payload || [];
return links.map((link) => Number(link.media_id)).filter(Boolean);
}