Trim page props and page the conversation's messages
Bot and workspace lists in page props leave out instructions, memory and workspace context, and carry the last message as a short preview. The header avatar's edit form loads the bot's instructions when it opens. The conversation renders its latest 30 messages and loads older ones as the thread scrolls to its top. Also: the composer shows a placeholder until its editor loads, and `bun start` no longer builds first. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import type { BUN_SQLITE_COBBLE_WORKSPACES } from "@/db/types/db";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import type { BotTextModel, PagePropsType } from "@/src/types";
|
||||
import railBots from "@/src/utils/rail-bots";
|
||||
import railWorkspaces from "@/src/utils/rail-workspaces";
|
||||
import grabBots from "../bots/grab-bots";
|
||||
import grabActiveBotTask from "../bots/grab-active-bot-task";
|
||||
import grabBotMessages from "../bots/grab-bot-messages";
|
||||
@@ -23,7 +27,8 @@ type Params = {
|
||||
* The page props of a conversation (`/admin/bots/<id>` or
|
||||
* `/admin/workspaces/<id>/bots/<id>`): the rail's crew (the workspace's
|
||||
* in a workspace) and workspaces, the bot, its active session (marked
|
||||
* read) and its messages, the text model it runs on, its computers,
|
||||
* read) and its latest `AppData.ConversationFirstMessages` messages (the
|
||||
* thread loads older ones as it scrolls), the text model it runs on, its computers,
|
||||
* tools and MCP servers and active task there, and whether its mic and
|
||||
* read-aloud have a model to run on. The full model settings are left to
|
||||
* the models modal: the install-wide catalog (`api/admin/harness/catalog`)
|
||||
@@ -63,7 +68,11 @@ export default async function grabConversationProps({
|
||||
bot.unread = 0;
|
||||
|
||||
const [bot_messages, bot_text_model, bot_computers, bot_task, bot_extensions, transcription, speech] = await Promise.all([
|
||||
grabBotMessages({ session_id: session.id!, user_id }),
|
||||
grabBotMessages({
|
||||
session_id: session.id!,
|
||||
user_id,
|
||||
limit: AppData.ConversationFirstMessages + 1,
|
||||
}),
|
||||
grabTextModel({ bot_id: bot.id, workspace_id: scope }),
|
||||
grabBotComputers({ bot_id: bot.id, workspace_id: scope }),
|
||||
grabActiveBotTask({ bot_id: bot.id, session_id: session.id }),
|
||||
@@ -72,13 +81,16 @@ export default async function grabConversationProps({
|
||||
hasHarnessModel({ harness: "speech", bot_id: bot.id, workspace_id: scope }),
|
||||
]);
|
||||
|
||||
const bot_messages_more = bot_messages.length > AppData.ConversationFirstMessages;
|
||||
|
||||
return {
|
||||
bots,
|
||||
bot,
|
||||
workspaces,
|
||||
workspace: conversation.workspace,
|
||||
bots: railBots({ bots }),
|
||||
bot: railBots({ bots: [bot] })[0],
|
||||
workspaces: railWorkspaces({ workspaces }),
|
||||
workspace: conversation.workspace ? withoutContext(conversation.workspace) : null,
|
||||
bot_session: session,
|
||||
bot_messages,
|
||||
bot_messages: bot_messages_more ? bot_messages.slice(1) : bot_messages,
|
||||
bot_messages_more,
|
||||
bot_text_model,
|
||||
bot_computers,
|
||||
bot_task,
|
||||
@@ -87,6 +99,14 @@ export default async function grabConversationProps({
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The open workspace without its shared context, which the conversation
|
||||
* never shows (the bot reads it from the database).
|
||||
*/
|
||||
function withoutContext({ system_prompt, ...workspace }: BUN_SQLITE_COBBLE_WORKSPACES) {
|
||||
return workspace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the harness is on and has a model to run on for the bot there.
|
||||
*/
|
||||
|
||||
@@ -9,6 +9,10 @@ import mediaToAttachment from "./media-to-attachment";
|
||||
type Params = {
|
||||
session_id: number | string;
|
||||
limit?: number;
|
||||
/**
|
||||
* Only messages older than this one, for loading further back.
|
||||
*/
|
||||
before_id?: number | null;
|
||||
/**
|
||||
* Whose conversation it is, so a reaction can show as the user's own.
|
||||
* Left out for the bot's own history reads, which don't need it.
|
||||
@@ -17,12 +21,14 @@ type Params = {
|
||||
};
|
||||
|
||||
/**
|
||||
* The latest messages of a session, oldest first, with their attachments,
|
||||
* The latest messages of a session (or the latest before `before_id`),
|
||||
* oldest first, with their attachments,
|
||||
* what each replies to, and (when `user_id` is given) its reactions.
|
||||
*/
|
||||
export default async function grabBotMessages({
|
||||
session_id,
|
||||
limit = 100,
|
||||
before_id,
|
||||
user_id,
|
||||
}: Params): Promise<BotMessageWithAttachments[]> {
|
||||
let sql = ``;
|
||||
@@ -30,13 +36,18 @@ export default async function grabBotMessages({
|
||||
sql += `SELECT * FROM (\n`;
|
||||
sql += ` SELECT * FROM bot_messages\n`;
|
||||
sql += ` WHERE session_id = ?\n`;
|
||||
|
||||
if (before_id) {
|
||||
sql += ` AND (created_at, id) < (SELECT created_at, id FROM bot_messages WHERE id = ?)\n`;
|
||||
}
|
||||
|
||||
sql += ` ORDER BY created_at DESC, id DESC\n`;
|
||||
sql += ` LIMIT ?\n`;
|
||||
sql += `) ORDER BY created_at ASC, id ASC\n`;
|
||||
|
||||
const res = await BunSQLite.sql<BUN_SQLITE_COBBLE_BOT_MESSAGES>({
|
||||
sql,
|
||||
values: [session_id, limit],
|
||||
values: before_id ? [session_id, before_id, limit] : [session_id, limit],
|
||||
});
|
||||
|
||||
const messages = res.payload || [];
|
||||
|
||||
Reference in New Issue
Block a user