Tie each hook to a session, picked in the hook form

A hook's calls used to run in whatever session was active at the time.
Now `bot_hooks.session_id` pins them to one session, open or closed
(null still follows the active one). The hook form picks where it runs
(the bot's own chat or one of its workspaces) and a session there, or a
new one of its own started beside the active one so the chat on screen
stays. A bot's proposed hook gets the session it was proposed in, and a
missing session is replaced on the next call. Changing place or session
is refused while a run is open; the computer stays only if reachable.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-25 17:08:12 +01:00
co-authored by Claude Opus 5.5
parent 69988e08fc
commit fb4c89fca1
26 changed files with 630 additions and 19 deletions
@@ -0,0 +1,40 @@
import BunSQLite from "@moduletrace/bun-sqlite";
import type { BUN_SQLITE_COBBLE_BOT_HOOKS } from "@/db/types/db";
import ensureBotSession from "../bot-sessions/ensure-bot-session";
import pickHookSession from "./pick-hook-session";
type Params = {
hook: BUN_SQLITE_COBBLE_BOT_HOOKS;
bot_id: number;
workspace_id: number | null;
};
/**
* The session a hook's call runs in: its own (`session_id`), open or
* closed, or the conversation's active one when it follows that. When its
* session is gone, a new one of its own takes its place and the hook is
* linked to it.
*/
export default async function resolveHookSession({ hook, bot_id, workspace_id }: Params): Promise<number> {
if (!hook.session_id) {
return Number((await ensureBotSession({ user_id: hook.user_id!, bot_id, workspace_id })).id);
}
const session_id = (await pickHookSession({
user_id: hook.user_id!,
bot_id,
workspace_id,
choice: Number(hook.session_id),
title: hook.title || `Hook ${hook.id}`,
missing_starts_new: true,
}))!;
if (session_id != Number(hook.session_id)) {
await BunSQLite.sql({
sql: `UPDATE bot_hooks SET session_id = ?, updated_at = ? WHERE id = ?`,
values: [session_id, Date.now(), hook.id!],
});
}
return session_id;
}