A bot's powers came from bots.kind alone, so only the coordinator could hand work to other bots. bot_types now works like user_types: a row with no workspace holds everywhere (the coordinator), one with a workspace only there (a workspace admin), and no row is a worker. bots.kind stays the legacy marker of the one coordinator for who sees it. The matrices in src/dict/bot-types-dict.ts say what each type may do, whom it may direct and who grants it, read by one generic interpreter (rbac/type-assignment.ts) that userTypeAssignment now wraps too. Every run reads its powers once (grabBotRunPowers) and the chat tools, task runs and task tools gate on them instead of kind; a run's powers are its type's and its user's together. In the workspace it leads, an admin hands tasks to the workers there (results relayed back to it), sets their instructions, adds tasks to their lists and keeps the workspace's context when its user may. Super admins and admins grant it from the workspace's settings or the chat header's menu, and the coordinator with set_bot_type. Admins are marked with a filled green shield beside their name across the workspace, kept live by pushBotUpdated's admin_workspace_ids. Co-Authored-By: Claude Opus 5.5 <[email protected]>
81 lines
3.0 KiB
TypeScript
81 lines
3.0 KiB
TypeScript
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;
|
|
/**
|
|
* The workspaces the bot is admin of (`grabBotRunPowers`): in one of
|
|
* them, create_task can also add to the other members' own lists.
|
|
*/
|
|
admin_workspace_ids?: number[];
|
|
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. A workspace
|
|
* admin's may add to the other members' own lists there.
|
|
*/
|
|
export default async function grabBotTaskTools({
|
|
user_id,
|
|
bot_id,
|
|
is_coordinator,
|
|
admin_workspace_ids = [],
|
|
workspace_id,
|
|
}: Params): Promise<HarnessTool[]> {
|
|
let workers: BUN_SQLITE_COBBLE_BOTS[] = [];
|
|
let members: 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));
|
|
} else if (workspace_id && admin_workspace_ids.includes(Number(workspace_id))) {
|
|
members = (await grabCrewWorkers({ workspace_id })).filter((member) => member.id != Number(bot_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, admin_workspace_ids, workspace_id }),
|
|
createTaskTool({
|
|
user_id,
|
|
bot_id,
|
|
workspace_id,
|
|
is_coordinator,
|
|
workers,
|
|
workspaces,
|
|
admin_workspace_ids,
|
|
members,
|
|
}),
|
|
updateTaskTool({ user_id, bot_id, is_coordinator, admin_workspace_ids, scopes }),
|
|
];
|
|
}
|