- Rail: Add icon with stacked form modals (bot, workspace, computer), coordinator, recent bots with "See all bots", Workspaces section, and a workspace mode listing only its crew - Workspaces: page for context, bots (per-workspace instructions and memory), computers (default, link, unlink), models and delete; conversations scoped per bot per workspace - Sessions: conversations split into searchable, reopenable sessions with carry-over summaries; sessions and new-session header icons - Computers: created and provisioned over the docker socket, home dir kept at DATA_DIR/computers/<id> after delete; super admins only - Models: workspace settings win over a bot's own, then the defaults - Pictures for bots and workspaces; bots editable from the header - Coordinator tools: update_workspace, set_bot_workspace_instructions Co-Authored-By: Claude Opus 5.5 <[email protected]>
63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
import { useState } from "react";
|
|
import type { BUN_SQLITE_COBBLE_BOT_MESSAGES } from "@/db/types/db";
|
|
import type { BotUpdatedData, BotWithLastMessage } from "@/src/types";
|
|
import useServerEvent from "./use-server-event";
|
|
|
|
type Params = {
|
|
bots: BotWithLastMessage[];
|
|
/**
|
|
* The conversation open now: its new messages don't count as unread.
|
|
*/
|
|
open_bot_id?: number;
|
|
/**
|
|
* Whose conversations the list shows: a workspace's, or (null) the
|
|
* bots' own chats. Messages elsewhere leave the list alone.
|
|
*/
|
|
workspace_id?: number | null;
|
|
};
|
|
|
|
/**
|
|
* The crew, kept current from server pushes: faces and status lines,
|
|
* latest messages, and unread for conversations that aren't open.
|
|
*/
|
|
export default function useLiveBots({ bots, open_bot_id, workspace_id = null }: Params) {
|
|
const [live, setLive] = useState(bots);
|
|
|
|
useServerEvent({
|
|
event: "server:bot-updated",
|
|
onData: (data: BotUpdatedData) =>
|
|
setLive((prev) =>
|
|
prev.map((bot) =>
|
|
bot.id == data.id
|
|
? { ...bot, face: data.face, status_line: data.status_line }
|
|
: bot,
|
|
),
|
|
),
|
|
});
|
|
|
|
useServerEvent({
|
|
event: "server:bot-message",
|
|
onData: (message: BUN_SQLITE_COBBLE_BOT_MESSAGES) => {
|
|
if ((message.workspace_id || null) != workspace_id) return;
|
|
|
|
setLive((prev) =>
|
|
prev.map((bot) =>
|
|
bot.id == message.bot_id
|
|
? {
|
|
...bot,
|
|
last_message_text: message.text,
|
|
last_message_at: Number(message.created_at) || Date.now(),
|
|
unread:
|
|
message.author == "bot" && bot.id != open_bot_id
|
|
? 1
|
|
: bot.unread,
|
|
}
|
|
: bot,
|
|
),
|
|
);
|
|
},
|
|
});
|
|
|
|
return live;
|
|
}
|