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:
@@ -1,6 +1,7 @@
|
||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import type { WorkspaceActivityItem } from "@/src/types";
|
||||
import botFaceSql from "@/src/utils/bot-face-sql";
|
||||
|
||||
type Params = {
|
||||
user_id: number | string;
|
||||
@@ -9,19 +10,21 @@ type Params = {
|
||||
|
||||
/**
|
||||
* The user's latest conversations in a workspace, most recent first, each
|
||||
* with the bot it's with, its message count and latest message. Empty
|
||||
* with the bot it's with (its face as the user sees it), its message count and latest message. Empty
|
||||
* sessions are left out unless active.
|
||||
*/
|
||||
export default async function grabWorkspaceActivity({
|
||||
user_id,
|
||||
workspace_id,
|
||||
}: Params): Promise<WorkspaceActivityItem[]> {
|
||||
const face = botFaceSql({ user_id, prefix: "bot_" });
|
||||
|
||||
const res = await BunSQLite.sql<WorkspaceActivityItem>({
|
||||
sql: `SELECT s.*,
|
||||
b.name AS bot_name,
|
||||
b.image_media_id AS bot_image_media_id,
|
||||
b.hue AS bot_hue,
|
||||
b.face AS bot_face,
|
||||
${face.sql},
|
||||
(SELECT COUNT(*) FROM bot_messages m WHERE m.session_id = s.id) AS message_count,
|
||||
(SELECT m.text FROM bot_messages m WHERE m.session_id = s.id ORDER BY m.created_at DESC, m.id DESC LIMIT 1) AS last_message_text
|
||||
FROM bot_sessions s
|
||||
@@ -33,7 +36,7 @@ export default async function grabWorkspaceActivity({
|
||||
))
|
||||
ORDER BY COALESCE(s.last_activity_at, s.created_at) DESC, s.id DESC
|
||||
LIMIT ?`,
|
||||
values: [workspace_id, user_id, AppData.WorkspaceActivityItems],
|
||||
values: [...face.values, workspace_id, user_id, AppData.WorkspaceActivityItems],
|
||||
});
|
||||
|
||||
return res.payload || [];
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { BotWithFace } from "@/src/types";
|
||||
import type {
|
||||
BUN_SQLITE_COBBLE_BOTS,
|
||||
BUN_SQLITE_COBBLE_WORKSPACE_BOTS,
|
||||
BUN_SQLITE_COBBLE_WORKSPACES,
|
||||
} from "@/db/types/db";
|
||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||
import workspaceBotsSql from "@/src/utils/crew-access/workspace-bots-sql";
|
||||
import workspacesSql from "@/src/utils/crew-access/workspaces-sql";
|
||||
import botFaceSql from "@/src/utils/bot-face-sql";
|
||||
import grabCrewRole from "../access/grab-crew-role";
|
||||
|
||||
type Params = {
|
||||
@@ -16,7 +17,10 @@ type Params = {
|
||||
|
||||
export type WorkspaceBotMembership = {
|
||||
workspace: BUN_SQLITE_COBBLE_WORKSPACES;
|
||||
bot: BUN_SQLITE_COBBLE_BOTS;
|
||||
/**
|
||||
* With the user's own face (`botFaceSql`).
|
||||
*/
|
||||
bot: BotWithFace;
|
||||
/**
|
||||
* Its `workspace_bots` row. Null for the coordinator, which works in
|
||||
* every workspace without one until it's given instructions there.
|
||||
@@ -47,11 +51,12 @@ export default async function grabWorkspaceBot({
|
||||
if (!workspace?.id) return null;
|
||||
|
||||
const bot_access = workspaceBotsSql({ role, workspace_id: workspace.id });
|
||||
const face = botFaceSql({ user_id });
|
||||
|
||||
const bot = (
|
||||
await BunSQLite.sql<BUN_SQLITE_COBBLE_BOTS>({
|
||||
sql: `SELECT b.* FROM bots b WHERE b.id = ? AND ${bot_access.sql} LIMIT 1`,
|
||||
values: [bot_id, ...bot_access.values],
|
||||
await BunSQLite.sql<BotWithFace>({
|
||||
sql: `SELECT b.*, ${face.sql} FROM bots b WHERE b.id = ? AND ${bot_access.sql} LIMIT 1`,
|
||||
values: [...face.values, bot_id, ...bot_access.values],
|
||||
})
|
||||
).payload?.[0];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user