Bots and workspaces each keep a list of work tracked until it's done, and the bots move it along themselves as they work. - tasks (one collection per bot or per workspace), task_notes (the progress log) and task_media (a deliverable or a reference file, its bytes a private media row served at /media/private/<id>) - statuses todo/doing/blocked/done/cancelled, with blocked_reason while only the user can unblock it - visibility as SQL in src/utils/task-access: a user's own bots and workspaces, a run's own list plus its workspaces, everything for the coordinator; every tool and endpoint resolves through it - list_tasks, create_task and update_task on every run, so a chat reply, a task and a routine all read the list, log progress and file what they produced - TasksNote on every run and TaskReminderNote in chat, so a greeting or a proposed next step brings pending work up in one measured line - tasks group on the workspace dashboard and a tasks modal in the conversation header, sharing one form, row and detail panel - a bot's or workspace's own chat uploads are read before the delete so none are stranded; bot files keep their folder Also corrects the README's RAM guidance and table alignment.
41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import BunSQLite from "@moduletrace/bun-sqlite";
|
|
import type { BUN_SQLITE_COBBLE_TASKS } from "@/db/types/db";
|
|
import AppError from "@/src/utils/app-error";
|
|
import botTaskScopesSql from "@/src/utils/task-access/bot-task-scopes-sql";
|
|
|
|
type Params = {
|
|
task_id: number | string;
|
|
/**
|
|
* The bot whose run is asking.
|
|
*/
|
|
bot_id: number | string;
|
|
is_coordinator: boolean;
|
|
};
|
|
|
|
/**
|
|
* The task, if the bot's run reaches it: its own, a workspace it works in,
|
|
* or anything at all for the coordinator. The gate every task tool makes
|
|
* before reading or changing one, so a tool argument can never widen a
|
|
* run's reach.
|
|
*/
|
|
export default async function grabRunTask({
|
|
task_id,
|
|
bot_id,
|
|
is_coordinator,
|
|
}: Params): Promise<BUN_SQLITE_COBBLE_TASKS> {
|
|
const access = botTaskScopesSql({ bot_id, is_coordinator });
|
|
|
|
const res = await BunSQLite.sql<BUN_SQLITE_COBBLE_TASKS>({
|
|
sql: `SELECT t.* FROM tasks t WHERE t.id = ? AND ${access.sql} LIMIT 1`,
|
|
values: [Number(task_id), ...access.values],
|
|
});
|
|
|
|
const task = res.payload?.[0];
|
|
|
|
if (!task?.id) {
|
|
throw new AppError(`Task #${task_id} isn't one you can work on.`);
|
|
}
|
|
|
|
return task;
|
|
}
|