Files
cobble/src/functions/backend/db/tasks/grab-run-task.ts
T
tben 7cb26c4e36 Add tasks: the crew's shared to-do list
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.
2026-10-22 05:57:50 +01:00

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;
}