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.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import type { BUN_SQLITE_COBBLE_BOTS, BUN_SQLITE_COBBLE_WORKSPACES } from "@/db/types/db";
|
||||
import grabCrewWorkers from "@/src/functions/backend/db/bots/grab-crew-workers";
|
||||
import grabUserWorkspaces from "@/src/functions/backend/db/workspaces/grab-user-workspaces";
|
||||
import grabStorageScopes from "@/src/utils/storage-access";
|
||||
import type { HarnessTool } from "../../../types";
|
||||
import createTaskTool from "./create-task-tool";
|
||||
import listTasksTool from "./list-tasks-tool";
|
||||
import updateTaskTool from "./update-task-tool";
|
||||
|
||||
type Params = {
|
||||
user_id: number | string;
|
||||
bot_id: number | string;
|
||||
/**
|
||||
* Whether the run is the coordinator, which reaches every task, can add
|
||||
* to any list and reaches every folder.
|
||||
*/
|
||||
is_coordinator: boolean;
|
||||
workspace_id?: number | string | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* The task tools every run gets (`src/harness/tools/bot/tasks/`): the
|
||||
* shared to-do list, one per bot and one per workspace, so a chat reply, a
|
||||
* task and a scheduled run all read it, move it along and file what they
|
||||
* produced. The coordinator's create_task may target any worker or
|
||||
* workspace; its update_task may link any file it can reach.
|
||||
*/
|
||||
export default async function grabBotTaskTools({
|
||||
user_id,
|
||||
bot_id,
|
||||
is_coordinator,
|
||||
workspace_id,
|
||||
}: Params): Promise<HarnessTool[]> {
|
||||
let workers: BUN_SQLITE_COBBLE_BOTS[] = [];
|
||||
let workspaces: BUN_SQLITE_COBBLE_WORKSPACES[] = [];
|
||||
let all_workspace_ids: number[] = [];
|
||||
|
||||
if (is_coordinator) {
|
||||
workers = await grabCrewWorkers({ workspace_id });
|
||||
workspaces = (await grabUserWorkspaces({ user_id })).filter((workspace) => !workspace.archived);
|
||||
all_workspace_ids = workspaces.map((workspace) => Number(workspace.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* `grabStorageScopes` wants a numeric bot id.
|
||||
*/
|
||||
const numeric_bot_id = Number(bot_id);
|
||||
|
||||
const scopes = grabStorageScopes({
|
||||
bot_id: numeric_bot_id,
|
||||
bot_kind: is_coordinator ? "coordinator" : "worker",
|
||||
workspace_id: workspace_id ? Number(workspace_id) : null,
|
||||
all_workspace_ids,
|
||||
});
|
||||
|
||||
return [
|
||||
listTasksTool({ user_id, bot_id, is_coordinator, workspace_id }),
|
||||
createTaskTool({ user_id, bot_id, workspace_id, is_coordinator, workers, workspaces }),
|
||||
updateTaskTool({ user_id, bot_id, is_coordinator, scopes }),
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user