Give every user their own bot face

A bot's face and status line live in bot_user_faces, one row per bot and
user, set by jobs for the user whose conversation they're in. Needs-you
and working only show to that user; every bot read overlays the viewer's
face (botFaceSql) and pushes go to the user a face change is for.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-19 13:58:26 +01:00
co-authored by Claude Opus 5.5
parent 47c58bc76b
commit ab25158d87
32 changed files with 448 additions and 181 deletions
@@ -1,15 +1,20 @@
import BunSQLite from "@moduletrace/bun-sqlite";
import type { BotWithFace } from "@/src/types";
import botFaceSql from "@/src/utils/bot-face-sql";
import type {
BUN_SQLITE_COBBLE_BOTS,
BUN_SQLITE_COBBLE_WORKSPACES,
} from "@/db/types/db";
type Params = {
computer_id: number | string;
/**
* Whose faces the bots show.
*/
user_id: number | string;
};
export type ComputerAccess = {
bots: BUN_SQLITE_COBBLE_BOTS[];
bots: BotWithFace[];
workspaces: BUN_SQLITE_COBBLE_WORKSPACES[];
};
@@ -20,14 +25,17 @@ export type ComputerAccess = {
*/
export default async function grabComputerAccess({
computer_id,
user_id,
}: Params): Promise<ComputerAccess> {
const face = botFaceSql({ user_id });
const [bots, workspaces] = await Promise.all([
BunSQLite.sql<BUN_SQLITE_COBBLE_BOTS>({
sql: `SELECT b.* FROM bots b
BunSQLite.sql<BotWithFace>({
sql: `SELECT b.*, ${face.sql} FROM bots b
JOIN bot_computers bc ON bc.bot_id = b.id
WHERE bc.computer_id = ?
ORDER BY b.kind = 'coordinator' DESC, b.name COLLATE NOCASE ASC, b.id ASC`,
values: [computer_id],
values: [...face.values, computer_id],
}),
BunSQLite.sql<BUN_SQLITE_COBBLE_WORKSPACES>({
sql: `SELECT w.* FROM workspaces w