Carry conversations into new sessions with a visible summary

- Bots get continue_in_new_session: the bot writes a title and summary,
  the session closes for good (read-only) and the new one opens with the
  summary as a "Carried over from the last session" message that links
  back to the old session.
- Continue in new session (conversation menu, sessions modal) and the
  automatic rollover at the session length do the same; New session now
  starts a fresh, unlinked session.
- Session length is an app setting in Settings > General.
- ?session_id= opens a session; a carried-over one shows a bar linking to
  where the conversation went on instead of the composer.
- The thread can open the previous session above the current one (shown
  only, never in the prompt), and replies get search_past_sessions and
  read_past_session.
- Sessions are named from their opening messages, not their latest, and
  a carried summary is labelled as the earlier session's.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-26 05:35:52 +01:00
co-authored by Claude Opus 5.5
parent 1e6833b5d8
commit cc109bc361
64 changed files with 2074 additions and 128 deletions
@@ -33,6 +33,10 @@ type Props = {
* This session has an active task.
*/
has_task?: boolean;
/**
* The conversation went on in another session: no reply is due here.
*/
moved_on?: boolean;
/**
* Quotes text selected in a message in the composer.
*/
@@ -42,9 +46,15 @@ type Props = {
*/
older?: {
has_more: boolean;
/**
* The thread reaches the start of its oldest session, which carries
* on from another one that can be opened above it.
*/
has_previous?: boolean;
loading: boolean;
error?: string;
loadOlder: () => void;
loadPrevious?: () => void;
};
};
@@ -53,7 +63,9 @@ type Props = {
* upward. Empty space belongs at the top. New messages announce politely.
* While the bot works on a reply or a task, a status row sits under the
* last one. Text selected in a message can be quoted in the composer.
* Older messages load as it scrolls to the top; the reversed column keeps
* Older messages load as it scrolls to the top, and at the start of a
* session that carries on from another, the earlier one can be opened
* above it (shown only, never put in the bot's prompt); the reversed column keeps
* the view where it was as they land above it. The thread follows new
* messages while it sits at its bottom, stays put while it's scrolled up
* and then offers a button to get back down.
@@ -65,6 +77,7 @@ export default function MessageThread({
reply_progress,
receiving,
has_task,
moved_on,
onQuote,
older,
}: Props) {
@@ -92,6 +105,14 @@ export default function MessageThread({
error={older.error}
onLoad={older.loadOlder}
/>
) : older?.has_previous && older.loadPrevious ? (
<OlderMessagesLoader
loading={older.loading}
error={older.error}
onLoad={older.loadPrevious}
label="Show the previous session"
manual
/>
) : null}
{groups.map((group) => (
<MessageGroupBlock
@@ -104,10 +125,13 @@ export default function MessageThread({
bot={bot}
progress={progress}
reply_progress={reply_progress}
awaiting_reply={isAwaitingReply({
last_message: messages[messages.length - 1],
face: bot.face,
})}
awaiting_reply={
!moved_on &&
isAwaitingReply({
last_message: messages[messages.length - 1],
face: bot.face,
})
}
receiving={receiving}
has_task={has_task}
/>