Names that fit the chat, and a way to change one
Two things about titles were wrong. Every chat spent a second completion on its name, including an agent chat whose opening words are already a title -- somebody starting one states an objective, not a topic. An agent chat now takes `fallback_title` from its first prompt and makes no request at all; an ordinary chat, which opens with a question whose *answer* is what makes a title worth asking for, is unchanged. And renaming existed only as the `/title` slash command, which set the heading and left the sidebar row showing the old name until the next reload -- a rename that looks half-applied is one people do twice. There are pencil buttons on the heading and on every sidebar row now, both PATCHing the route that was already there, and `update_chat` answers a rename with the out-of-band pair the `done` frame has always sent, so one response moves both. Only on a rename: sending it for every PATCH would overwrite the heading from an unrelated save. `/title` sets both spans itself, being a bare fetch rather than htmx. The dialog is the `data-prompt` mechanism the folder work added, which is why the heading keeps a button rather than becoming an inline field: it sits in a flex row beside the badges and the connection chip, and swapping it for a text box moves all of them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -406,6 +406,13 @@ async def _run(generation: Generation) -> None:
|
||||
)
|
||||
question = _question_from(payload)
|
||||
needs_title = not chat.title_generated
|
||||
# An agent chat is titled from its opening words and never costs a
|
||||
# model call for it. That prompt is a good title already -- somebody
|
||||
# starting one states an objective, not a topic -- while an ordinary
|
||||
# chat opens with a question, whose answer is what makes a title
|
||||
# worth asking for. Read here with the rest, because titling happens
|
||||
# after this session has closed.
|
||||
title_from_prompt = chat.kind == KIND_AGENT
|
||||
# Read here, with the rest, because titling happens after this
|
||||
# session has closed and must not open another one.
|
||||
title_prompt = prompts_service.resolve(db, "task.title")
|
||||
@@ -714,7 +721,7 @@ async def _run(generation: Generation) -> None:
|
||||
# a chat title is never worth surfacing an error for.
|
||||
title = ""
|
||||
if needs_title and question:
|
||||
if generation.error or endpoint is None:
|
||||
if title_from_prompt or generation.error or endpoint is None:
|
||||
title = chat_service.fallback_title(question)
|
||||
else:
|
||||
with contextlib.suppress(Exception):
|
||||
|
||||
Reference in New Issue
Block a user